c - valgrind 中大小为 1 的无效写入/读取,未找到答案

标签 c linux memory-management valgrind

我正在尝试对无法用经典数字类型表示的数字进行质数分解。 我将那个大数字读取为字符串,然后将它除以所有小于 10^6(提前生成)的素数。在过程中我使用内存的动态分配。完成我的代码后,我检查了 valgrind 输出并发现了一些错误,这些错误似乎是由同一件事引起的,我只是看不出我的代码有什么问题。我做了一项研究,虽然很多人都遇到了同样的错误,但解决方案不适用于我的问题。 我会很感激每一条建议,因为我现在很绝望。

这是我的代码(没有对我的问题没有实质意义的功能):

long* primeArray;
long endDiv = 101;
long r;
long length;
char *division(char dividend[],long divisor){
    char *multiplier = malloc(sizeof(char*)*endDiv);
    long temp=0;
    int i=0;
    int j=0;
    while(dividend[i]){  
         temp = temp*10 + (dividend[i] - 48);
         if(temp<divisor){
             multiplier[j++] = 48;
         }
         else{
             multiplier[j++] = (temp / divisor) + 48;
             temp = temp % divisor;
         }
         i++;
    }
    multiplier[j] = '\0';
    length = j;
    r = temp;
    return multiplier;
}
void doDecomposition(char* divident){
    long* primeDec = (long*)malloc(endDiv* sizeof(long*));
    int counter = 0;
    char * multiplier;  
    for(int i = 0;i<endPrime-1;i++){
            multiplier = division(divident, primeArray[i]);
            if(r == 0){
                free(divident);                 
                divident = multiplier;
                primeDec[counter] = primeArray[i];
                i = -1;
                counter++;
            }else{
                int f = 0;
                for(int a = length-1;a>0;a--){
                    if(multiplier[a] != '0'){
                        f = 1;
                        break;
                    }
                }
                free(multiplier);
                if(f==0){
                    break;
                }
            }   
    }
    printCount(primeDec, counter);
    free(primeDec);
    free(divident);
}
int main(int argc, char *argv[])
{
    char* divident = malloc(endDiv*sizeof(char*));
    genPrime(1000000);
    if(divident == NULL){
        exit(666);
    }
    while(fscanf(stdin, "%s", divident) == 1){  
        if(divident[0] == '0' && divident[1]=='\0'){
            exit(0);
        }
        else if(divident[0] == '1' && divident[1]=='\0'){
            fprintf(stdout, "Prime decomposition of 1 is:\n1\n");
        }
        else{
            checkDivident(divident);
            fprintf(stdout,"Prime decomposition of %s is:\n", divident);
            doDecomposition(divident);
        }   
    }
    free(divident); 
  return 0;
}

这是我的 valgrind 输出:

==17523== Invalid write of size 1
==17523==    at 0x51A0695: _IO_vfscanf (vfscanf.c:1107)
==17523==    by 0x51AE8E8: __isoc99_fscanf (isoc99_fscanf.c:34)
==17523==    by 0x40126F: main (main.c:185)
==17523==  Address 0x550c040 is 0 bytes inside a block of size 808 free'd
==17523==    at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17523==    by 0x401128: doDecomposition (main.c:161)
==17523==    by 0x401252: main (main.c:195)
==17523==  Block was alloc'd at
==17523==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17523==    by 0x400C8A: division (main.c:73)
==17523==    by 0x401080: doDecomposition (main.c:145)
==17523==    by 0x401252: main (main.c:195)
==17523== 
==17523== Invalid write of size 1
==17523==    at 0x51A0752: _IO_vfscanf (vfscanf.c:1192)
==17523==    by 0x51AE8E8: __isoc99_fscanf (isoc99_fscanf.c:34)
==17523==    by 0x40126F: main (main.c:185)
==17523==  Address 0x550c041 is 1 bytes inside a block of size 808 free'd
==17523==    at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17523==    by 0x401128: doDecomposition (main.c:161)
==17523==    by 0x401252: main (main.c:195)
==17523==  Block was alloc'd at
==17523==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17523==    by 0x400C8A: division (main.c:73)
==17523==    by 0x401080: doDecomposition (main.c:145)
==17523==    by 0x401252: main (main.c:195)
==17523== 
==17523== Invalid read of size 1
==17523==    at 0x4011C4: main (main.c:186)
==17523==  Address 0x550c040 is 0 bytes inside a block of size 808 free'd
==17523==    at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17523==    by 0x401128: doDecomposition (main.c:161)
==17523==    by 0x401252: main (main.c:195)
==17523==  Block was alloc'd at
==17523==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17523==    by 0x400C8A: division (main.c:73)
==17523==    by 0x401080: doDecomposition (main.c:145)
==17523==    by 0x401252: main (main.c:195)
==17523== 
==17523== Invalid read of size 1
==17523==    at 0x4011D3: main (main.c:186)
==17523==  Address 0x550c041 is 1 bytes inside a block of size 808 free'd
==17523==    at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17523==    by 0x401128: doDecomposition (main.c:161)
==17523==    by 0x401252: main (main.c:195)
==17523==  Block was alloc'd at
==17523==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17523==    by 0x400C8A: division (main.c:73)
==17523==    by 0x401080: doDecomposition (main.c:145)
==17523==    by 0x401252: main (main.c:195)
==17523== 
==17523== 
==17523== HEAP SUMMARY:
==17523==     in use at exit: 627,992 bytes in 1 blocks
==17523==   total heap usage: 1,252,545 allocs, 1,252,544 frees, 1,504,746,312 bytes allocated
==17523== 
==17523== LEAK SUMMARY:
==17523==    definitely lost: 0 bytes in 0 blocks
==17523==    indirectly lost: 0 bytes in 0 blocks
==17523==      possibly lost: 0 bytes in 0 blocks
==17523==    still reachable: 627,992 bytes in 1 blocks
==17523==         suppressed: 0 bytes in 0 blocks
==17523== Reachable blocks (those to which a pointer was found) are not shown.
==17523== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==17523== 
==17523== For counts of detected and suppressed errors, rerun with: -v
==17523== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)

行号信息:

185: while(fscanf(stdin, "%s", divident) == 1){ 
161: free(multiplier);
195: doDecomposition(divident);
73: char *multiplier = malloc(sizeof(char*)*endDiv);
145: multiplier = division(divident, primeArray[i]);

感谢您所做的一切,即使是最细微的线索,我也会很高兴!

最佳答案

问题是您在 doDecomposition 函数中释放了除法器。 因此,如果条件 if(r == 0) 为真,则在 main 中执行的下一个循环中,您尝试写入不属于您的内存.如果在循环中,您已经在程序结束时释放了它,为什么要释放它?

另一个问题,你为什么做 if(divident[0] == '0' && divident[1]=='\0') ?阅读 strcmp 手册,它更具可读性,也更易于使用;)

最后一件事,当你 malloc 时,我认为 int *i = malloc(sizeof(*i));int *i = malloc(sizeof(int*)) ;,因为如果你想改变 i 的类型,你必须用正确的类型改变每个分配。如果你有一个小程序,这不是问题,但如果有一个大程序,那就更难了。

关于c - valgrind 中大小为 1 的无效写入/读取,未找到答案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40459684/

相关文章:

c - 为什么 C 源代码有时会包含 do...while(0) 循环?

c - 重新声明全局变量与局部变量

MySQL 作为 Linux (Ubuntu) 中 SQL Server 2008 的桥梁

linux - 从 bash 脚本打开 iTerm2 并运行命令

java - 已用、已提交和最大堆内存的差异

c - 删除未使用的变量会导致崩溃

c - 我怎样才能获得所有文件的列表及其在c中的路径

linux - 未找到 Bash 脚本,尽管它在 $PATH 中

objective-c - 当你声明一个对象时,Objective-C 实际上做了什么?

c++ - 一个关于内存使用的简单C++问题