简体   繁体   English

C语言中变量声明的排列方式确定执行哪一个?

[英]Arrangement of variable declarations in C determines which one gets executed?

Need serious help - I am encountering a very weird problem. 需要认真的帮助-我遇到一个非常奇怪的问题。

My program is a program that defines different structures in a library file Test.h . 我的程序是在库文件Test.h中定义不同结构的程序。 This is the Test.h file: 这是Test.h文件:

typedef struct InstructionFields{ 
  unsigned int op;         /* opcode: bits 31-26 */
  unsigned int rs;         /* first register source operand: bits 25-21 */
  unsigned int rt;         /* second register source operand: bits 20-16 */
  unsigned int rd;          /* destination register: bits 15-11 */
  unsigned int shamt;      /* shift amount: bits 10-6 */
  unsigned int immedOrAddress;      /* constant or address: bits 15-0 */ 
  unsigned int target;    /* jump target: bits 25-0 */
  unsigned int funct;      /* function: bits 5-0 */
} IF, *IF_ptr;

typedef struct ControlSignalsList{ 
  unsigned int RegDst;         /* Register Destination */
  unsigned int RegWrite;         /* Write Register */
  unsigned int ALUSrc;         /* ALU Source */
  unsigned int MemRead;      /* Mem Read */
  unsigned int MemWrite;      /* Mem Write */ 
  unsigned int MemtoReg;      /* Memory to Register*/
  unsigned int ALUControl ;    /*4 bit ALU control */
  unsigned int Branch;         /* BEQ */
  unsigned int Jump;          /* Jump*/
} CS, *CS_ptr;

typedef struct RegisterStructure{ 
  int t0;         /* Register t0 */
  int t1;         /* Register t1 */
  int t2;         /* Register t2 */
  int t3;         /* Register t0 */
  int ReadData1;      /* Read Data 1 buffer */
  int ReadData2;      /* Read Data 2 buffer */ 
  int WriteReg; 
  unsigned int readReg1;   /* address of rs */
  unsigned int readReg2;   /* address of rt */
   /* WriteReg */
} RG, *RG_ptr;

typedef struct ALUStructure{
  int DataOut;
  unsigned int Zero;
} AS, *AS_ptr;

Next, a file Test.c includes this library, declares variables that use these structures, and then assigns values to different fields of the structure. 接下来,文件Test.c包括该库,声明使用这些结构的变量,然后将值分配给该结构的不同字段。

This is the Test.c file: 这是Test.c文件:

#include "Test.h"
#include <stdio.h>

int main() {
 CS_ptr controlSignals;         // Line 5
 IF_ptr iFields;                // Line 6
 RG_ptr registers;              // Line 7 
 AS_ptr as;                     // Line 8

 controlSignals->RegDst = 0;    // Line 11
 //registers->t0 = 0;           // Line 12
 //iFields->op = 0;             // Line 13
 //as->DataOut = 0;             // Line 14

 printf("This is fine\n");
return 0;
}

The code above is working fine. 上面的代码工作正常。 But as soon as I uncomment line 12, a segmentation fault occurs: Segmentation fault: 11 . 但是,一旦我取消注释第12行,就会发生Segmentation fault: 11 I used valgrind and this is the error message: 我使用了valgrind,这是错误消息:

==2002== Use of uninitialised value of size 8
==2002==    at 0x100000F5A: main (test.c:11)
==2002== 
==2002== Use of uninitialised value of size 8
==2002==    at 0x100000F64: main (test.c:12)
==2002== 
==2002== Invalid write of size 4
==2002==    at 0x100000F64: main (test.c:12)
==2002==  Address 0x0 is not stack'd, malloc'd or (recently) free'd

==2002== Process terminating with default action of signal 11 (SIGSEGV)
==2002==  Access not within mapped region at address 0x0
==2002==    at 0x100000F64: main (test.c:12)
==2002==  If you believe this happened as a result of a stack
==2002==  overflow in your program's main thread (unlikely but
==2002==  possible), you can try to increase the size of the
==2002==  main thread stack using the --main-stacksize= flag.
==2002==  The main thread stack size used in this run was 8388608.

At first I thought it was a problem of unitialized pointers, so I initialized the pointers to NULL . 起初,我认为这是一个统一指针的问题,因此我将指针初始化为NULL But it didn't fix anything, and even created more segmentation faults. 但是它并没有解决任何问题,甚至造成了更多的分段错误。 So I left them alone. 所以我让他们独自一人。

Then, I tried moving things around. 然后,我尝试移动东西。 Weirdly, if I move Line 7 to the top before Line 5 (to declare RG_ptr first), and uncomment Line 11, then registers->t0 = 0 gets executed and the segmentation fault is fixed! 奇怪的是,如果我将第7行RG_ptr第5行之前的顶部(首先声明RG_ptr ),并且取消注释第11行,则将执行registers->t0 = 0并修复了分段错误!

The same thing happens to the other pointer declarations. 其他指针声明也发生同样的事情。 Only when a pointer declaration is at the beginning does the corresponding field assignment get executed. 仅当指针声明位于开头时,才会执行相应的字段分配。 Any other field assignments, when uncommented, cause segmentation faults. 如果未注释任何其他字段分配,则会导致分段错误。

What is going on? 到底是怎么回事? How can this problem be fixed? 如何解决此问题? I appreciate any help! 感谢您的帮助!

The problematic code is: 有问题的代码是:

RG_ptr registers;
registers->t0 = 0;

Note that RG_ptr is a pointer and it's never initialized. 请注意, RG_ptr是一个指针 ,并且从未初始化。 Using an uninitialized pointer is undefined behaviour and your program crashes. 使用未初始化的指针是未定义的行为,并且您的程序崩溃。

A NULL pointer is not actually "initialized". NULL指针实际上并未“初始化”。 That just makes a null pointer, and that's pointing at invalid memory. 那只会产生一个空指针,并且指向无效的内存。 You can't dereference that pointer without crashes either. 您也不能在没有崩溃的情况下取消引用该指针。 Normally people use null pointers to indicate something that's "not assigned" or "not relevant" as opposed to being uninitialized which means the pointer can contain garbage data. 通常,人们使用空指针来表示“未分配”或“不相关”的东西,这与未初始化相反,这意味着指针可以包含垃圾数据。

You must initialize that pointer by allocating memory, or pointing it an existing RG structure. 您必须通过分配内存或将其指向现有的RG结构来初始化该指针。

For example: 例如:

RG registers;
RG_ptr registers_pointer = &registers;

Or: 要么:

RG_ptr registers = malloc(sizeof(RG));

Remember that if you're using allocated memory you need to be extremely disciplined about ensuring all allocations have corresponding deallocations with free or you will leak memory. 请记住,如果您正在使用分配的内存,则必须严格遵守有关确保所有分配都具有free相应释放的严格约束,否则会泄漏内存。

You have not allocated space for the structures. 您尚未为结构分配空间。 And when dereference uninitialized pointer you get segfault which is expectable. 当取消引用未初始化的指针时,您会得到预期的segfault。

BTW newer typedef pointers. BTW较新的typedef指针。

RG *registers; RG *注册; RG_ptr registers; RG_ptr寄存器;

The second declaration does not look like pointer. 第二个声明看起来不像指针。 It is a potential source of the hard to spot errors. 这是难以发现错误的潜在来源。 Use stars for the pointers. 使用星号作为指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM