Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 无效的写入/读取错误,在其他问题中找不到解决方案_C_Valgrind - Fatal编程技术网

C 无效的写入/读取错误,在其他问题中找不到解决方案

C 无效的写入/读取错误,在其他问题中找不到解决方案,c,valgrind,C,Valgrind,我正在为一个家庭作业编写C代码,该作业通过一个动态内存段数组复制主内存 这些内存段来自另一个接口,它本身只是一个uint32_t的静态数组 我的主内存接口名为heapmem(如堆内存),自切换以来,我一直遇到奇怪的valgrind读/写错误。在把我吐出来之前,我已经看过并研究过了,作为最后的手段,我要这么做 这是错误 ==30352== Invalid write of size 8 ==30352== at 0x401661: HeapMem_map (heapmem.c:84) ==3

我正在为一个家庭作业编写C代码,该作业通过一个动态内存段数组复制主内存

这些内存段来自另一个接口,它本身只是一个uint32_t的静态数组

我的主内存接口名为heapmem(如堆内存),自切换以来,我一直遇到奇怪的valgrind读/写错误。在把我吐出来之前,我已经看过并研究过了,作为最后的手段,我要这么做

这是错误

==30352== Invalid write of size 8
==30352==    at 0x401661: HeapMem_map (heapmem.c:84)
==30352==    by 0x400E74: map (um.c:109)
==30352==    by 0x4010FD: runOpcode (um.c:182)
==30352==    by 0x4011A1: UM_run (um.c:209)
==30352==    by 0x400A71: main (main.c:10)
==30352==  Address 0x4c53b00 is 0 bytes after a block of size 16 alloc'd
==30352==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==30352==    by 0x401425: HeapMem_new (heapmem.c:32)
==30352==    by 0x400ABE: UM_new (um.c:31)
==30352==    by 0x400A64: main (main.c:8)
==30352== 
==30352== Invalid read of size 8
==30352==    at 0x401787: HeapMem_put (heapmem.c:114)
==30352==    by 0x400D38: sstore (um.c:90)
==30352==    by 0x401090: runOpcode (um.c:167)
==30352==    by 0x4011A1: UM_run (um.c:209)
==30352==    by 0x400A71: main (main.c:10)
==30352==  Address 0x4c53b00 is 0 bytes after a block of size 16 alloc'd
==30352==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==30352==    by 0x401425: HeapMem_new (heapmem.c:32)
==30352==    by 0x400ABE: UM_new (um.c:31)
==30352==    by 0x400A64: main (main.c:8)
==30352== 
==30352== Invalid read of size 8
==30352==    at 0x401956: car_double (heapmem.c:151)
==30352==    by 0x401640: HeapMem_map (heapmem.c:82)
==30352==    by 0x400E74: map (um.c:109)
==30352==    by 0x4010FD: runOpcode (um.c:182)
==30352==    by 0x4011A1: UM_run (um.c:209)
==30352==    by 0x400A71: main (main.c:10)
==30352==  Address 0x4c53b00 is 0 bytes after a block of size 16 alloc'd
==30352==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==30352==    by 0x401425: HeapMem_new (heapmem.c:32)
==30352==    by 0x400ABE: UM_new (um.c:31)
==30352==    by 0x400A64: main (main.c:8)
==30352== 
==30352== Invalid read of size 8
==30352==    at 0x40174A: HeapMem_get (heapmem.c:108)
==30352==    by 0x400CD9: sload (um.c:86)
==30352==    by 0x401079: runOpcode (um.c:164)
==30352==    by 0x4011A1: UM_run (um.c:209)
==30352==    by 0x400A71: main (main.c:10)
==30352==  Address 0x4c7e0f0 is 0 bytes after a block of size 4,096 alloc'd
==30352==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==30352==    by 0x401923: car_double (heapmem.c:148)
==30352==    by 0x401640: HeapMem_map (heapmem.c:82)
==30352==    by 0x400E74: map (um.c:109)
==30352==    by 0x4010FD: runOpcode (um.c:182)
==30352==    by 0x4011A1: UM_run (um.c:209)
==30352==    by 0x400A71: main (main.c:10)
以下是代码中给出错误的函数:

//  Heap Memory Structure
struct T {
   Stack_T SegID_stack;
   MemSeg_T* HeapMem_car;
   int length, highest;
};

//  Create a new heap memory structure
T HeapMem_new (MemSeg_T program) {
    assert (program);
    T retHeap = malloc(sizeof(*retHeap));
    Stack_T structStack = Stack_new ();
    retHeap->length = INIT_SIZE;
    retHeap->highest = 0;
    MemSeg_T* structCar = malloc(INIT_SIZE * sizeof(*structCar));
    //  Fill the array with NULL ptrs
    for (int i = 0; i < INIT_SIZE; i++) {
        structCar[i] = NULL;
    }
    retHeap->HeapMem_car = structCar;
    retHeap->SegID_stack = structStack;
    //  We'll be using the map function to initialize
    //  the heap with a program at the 0th segment.
    HeapMem_map (retHeap, MemSeg_length (program));
    retHeap->HeapMem_car[PROGRAM_LOC] = program;
    return retHeap;
}

//  Line 84
heapmem->HeapMem_car[toMap] = segment;
//  Line 114
MemSeg_T segToPut = heapmem->HeapMem_car[toPut];
//  Line 151
newCar[i] = heapmem->HeapMem_car[i];
//  Line 108
MemSeg_T wordSeg = heapmem->HeapMem_car[toGet];
//堆内存结构
结构T{
Stack_T SegID_Stack;
汽车;
整数长度,最高;
};
//创建一个新的堆内存结构
T HeapMem_新(MemSeg_T计划){
断言(程序);
T retHeap=malloc(sizeof(*retHeap));
Stack_T structStack=Stack_new();
retHeap->length=INIT_SIZE;
retHeap->highest=0;
MemSeg_T*structCar=malloc(初始大小*sizeof(*structCar));
//用空ptr填充数组
对于(int i=0;iHeapMem\u car=structCar;
retHeap->SegID_stack=structStack;
//我们将使用map函数进行初始化
//在第0段具有程序的堆。
HeapMem_映射(retHeap,MemSeg_长度(程序));
RETCHEAP->HeapMem\U car[PROGRAM\U LOC]=程序;
返回retHeap;
}
//第84行
heapmem->heapmem\u car[toMap]=段;
//第114行
MemSeg_T segToPut=heapmem->heapmem_car[toPut];
//第151行
新车[i]=heapmem->heapmem_车[i];
//第108行
MemSeg_T wordSeg=heapmem->heapmem_car[toGet];

其余代码可用。

首先对您的一个错误进行一个小剖析:

==30352== Invalid write of size 8
==30352==    at 0x401661: HeapMem_map (heapmem.c:84)
==30352==    by 0x400E74: map (um.c:109)
==30352==    by 0x4010FD: runOpcode (um.c:182)
==30352==    by 0x4011A1: UM_run (um.c:209)
==30352==    by 0x400A71: main (main.c:10)
==30352==  Address 0x4c53b00 is 0 bytes after a block of size 16 alloc'd
==30352==    at 0x4A0610C: malloc (vg_replace_malloc.c:195)
==30352==    by 0x401425: HeapMem_new (heapmem.c:32)
==30352==    by 0x400ABE: UM_new (um.c:31)
==30352==    by 0x400A64: main (main.c:8)
请注意,此列表的底部告诉您分配发生的位置。上面告诉你它是如何被滥用的。在本例中,您正好经过请求分配的末尾8个字节

您将注意到其中的所有溢出,其余的冲突超出了它们的能力范围,达到了完全相同的偏移量(8字节)。对引用代码的进一步检查表明,它似乎总是相同的数组。这实际上是一件好事,因为很可能只是错误地计算数据项的存在方式,并超出允许的空间到达一个或两个

在这种情况下,被破坏的项似乎是一个动态分配的指针列表(
heapmem->heapmem\u car[]
)。在具有64位指针的机器上运行会使每个指针的宽度为8字节,因此您可能只需在该分配的最后一个可访问元素中减去1,而在C中,这通常意味着在某个点分配
N
项,然后访问
array[N]
而忘记了限制是
N-1
。上面所有的访问冲突似乎都围绕着这样一个信念,即进入该数组的索引并没有超出范围,但valgrind报告说它们确实超出范围。我建议您将一些assert()插入这些访问点,并在违反时中断,以查看您是如何做到这一点的。哦,等等。。valgrind已经为你提供了这些信息。看看那个可爱的呼叫堆栈。嗯

那么,为什么即使有这些违规行为,它似乎也能起作用呢?许多可能性。如果您没有超出分配的内存,那么这里的所有地址都是0字节后的-(这些毕竟是指针,请祈祷它们为空)很有可能您不会覆盖重要数据,并且程序似乎可以工作。直到分配突然落到其他地方,您跨过页面边界。超过这一点,就会爆炸


感谢您对本答案第二部分的贡献(为什么它看起来有效)。

这些不是类型,而是变量名。int*n=malloc(sizeof(*n))与=malloc(sizeof(int))相同,我认为初始构造没有明显的错误,假设Stack_new()返回有效的分配,并且retHeap的所有成员都正确初始化(这里没有它们的定义也很难说)。valgrind中的错误告诉您这是分配内存和违反访问的地方
map()
store()
似乎都在请求命中超出您在此处所做的分配。请立即给出定义,抱歉!在heapxxx函数族中,如何防止对
heapmem->heapmem\u car[]
持有的内存进行越界访问?上面所有的访问冲突似乎都围绕着这样一个信念,即进入该数组的索引并没有超出范围,但valgrind报告说它们确实超出范围。我建议您将一些
assert()
s插入这些访问点,并在违规时中断,看看您是如何做到的。但它运行良好,这是奇怪的部分。所有这些错误,但它仍然运行。直到分配突然到达其他地方,您跨过页面边界。← 这将是仁慈的失败模式。由于这是堆内存,如果填充和对齐不发生干扰,您将覆盖连续的内存块。最坏的情况是该数据块中的数据发生无声损坏。更温和的情况是稍后崩溃:覆盖连续块上的控制结构,如果该块稍后被释放(或者如果该块以任何形式被访问,例如:试图合并相邻的空闲块),则可能会导致崩溃。