无效写入大小为8的C Valgrind,字符串数组 [英] Invalid write of size 8, C Valgrind, string arrays

查看:141
本文介绍了无效写入大小为8的C Valgrind,字符串数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用valgrind和gdb,但我不太清楚问题出在哪里.对于我而言,要想在gdb中真正找到它,它跳得太多了,而在valgrind中,我没有足够的信息.这是我的makeargv函数,该函数将从strtok()输出的字符串放入数组中.从下面的解析函数中调用makeargv.我不确定我要去哪里.我非常感谢您的帮助:D.

I have been using both valgrind and gdb and I can not quite figure out what the problem is. It hops around too much for me to really trace it down in gdb, and in valgrind I don't have enough information. Here is my makeargv function, which is putting strings outputted from strtok() into arrays. makeargv is called from the below parse function. I'm not sure where I'm going wrong. I would really appreciate the help :D.

仅供参考,我真的对所有这些分配都是陌生的,并且并没有真正理解我想要的概念.我不确定我什么时候应该分配内存.我觉得自此以来,我主要是在设置常量值,而不必设置,但是我想知道为什么它不起作用.

Just an FYI I'm really new to all this malloc'ing and don't really understand the concept as well as I would like. I'm not sure when specifically I should be mallocing. I feel like since here I am mainly setting constant values I don't have to be, but I'm wondering why it won't work.

makeargv函数

makeargv function

int makeargv(const char *string, char **argvp) {
    int i = 0;
    int numtokens = 0;
    const char *copy;
    char *buffer = malloc(160*sizeof(char));

    if ((string == NULL) || (delims == NULL) || (argvp == NULL)) {
      return -1;
    }

    argvp = NULL;
    copy = string + strspn(string, delims);
    if ((buffer = malloc(strlen(copy) + 1)) == NULL) {
      return -1;
    }
    strcpy(buffer, copy);
    numtokens = 0;
    if (strtok(buffer, delims) != NULL) {
      for (numtokens = 1; strtok(NULL, delims) != NULL; numtokens++);
    }

    if ((argvp = malloc((numtokens + 2)*sizeof(int))) == NULL) {
      free(buffer);
      return -1;
    }

    if (numtokens == 0) {
      free(buffer);
    }
    else {
      strcpy(buffer, copy);
      *argvp = malloc(16);
      *argvp = strtok(buffer, delims);

      for (i = 2; i < (numtokens*2); i += 2) {
      *(argvp + i) = strtok(NULL, delims);
      //printf("%s\n", strtok(NULL, delims)); /*When I run this the tokens come out
      correctly so I know it isn't a problem with strtok */
  }
}

//  *((argvp) + numtokens) = NULL;
free(buffer);
return numtokens;
}

解析函数

void parse_file(char* filename) {
    char* line = malloc(160*sizeof(char));
    FILE* fp = file_open(filename);
    int i = 0;

    while((line = file_getline(line, fp)) != NULL) {
      char** results = malloc(16*10*sizeof(char));

      if (strlen(line) == 1){
        continue;
      }

      if ((i = makeargv(line, results)) == -1){
        printf("ERROR SOMEWHERE IN MAKEARGV");
        continue;
      } 
    }

    fclose(fp);
    free(line);
}

valgrind输出

valgrind output

==7309== Memcheck, a memory error detector
==7309== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==7309== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==7309== Command: ./custmake
==7309== 
==7309== Invalid write of size 8
==7309==    at 0x400C23: makeargv (main.c:62)
==7309==    by 0x400CD4: parse_file (main.c:120)
==7309==    by 0x400DFF: main (main.c:172)
==7309==  Address 0x51f25c0 is 16 bytes inside a block of size 20 alloc'd
==7309==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309==    by 0x400B76: makeargv (main.c:49)
==7309==    by 0x400CD4: parse_file (main.c:120)
==7309==    by 0x400DFF: main (main.c:172)
==7309== 
==7309== Use of uninitialised value of size 8
==7309==    at 0x4C2BFC2: __GI_strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309==    by 0x4EA2CEB: puts (ioputs.c:37)
==7309==    by 0x400D09: parse_file (main.c:128)
==7309==    by 0x400DFF: main (main.c:172)
==7309== 
==7309== Invalid read of size 1
==7309==    at 0x4C2BFC2: __GI_strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309==    by 0x4EA2CEB: puts (ioputs.c:37)
==7309==    by 0x400D09: parse_file (main.c:128)
==7309==    by 0x400DFF: main (main.c:172)
==7309==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==7309== 
==7309== 
==7309== Process terminating with default action of signal 11 (SIGSEGV)
==7309==  Access not within mapped region at address 0x0
==7309==    at 0x4C2BFC2: __GI_strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309==    by 0x4EA2CEB: puts (ioputs.c:37)
==7309==    by 0x400D09: parse_file (main.c:128)
==7309==    by 0x400DFF: main (main.c:172)
==7309==  If you believe this happened as a result of a stack
==7309==  overflow in your program's main thread (unlikely but
==7309==  possible), you can try to increase the size of the
==7309==  main thread stack using the --main-stacksize= flag.
==7309==  The main thread stack size used in this run was 8388608.
==7309== 
==7309== HEAP SUMMARY:
==7309==     in use at exit: 1,084 bytes in 6 blocks
==7309==   total heap usage: 7 allocs, 1 frees, 1,100 bytes allocated
==7309== 
==7309== 16 bytes in 1 blocks are definitely lost in loss record 1 of 6
==7309==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309==    by 0x400BCB: makeargv (main.c:59)
==7309==    by 0x400CD4: parse_file (main.c:120)
==7309==    by 0x400DFF: main (main.c:172)
==7309== 
==7309== 20 bytes in 1 blocks are definitely lost in loss record 2 of 6
==7309==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309==    by 0x400B76: makeargv (main.c:49)
==7309==    by 0x400CD4: parse_file (main.c:120)
==7309==    by 0x400DFF: main (main.c:172)
==7309== 
==7309== 160 bytes in 1 blocks are definitely lost in loss record 5 of 6
==7309==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309==    by 0x400A6E: makeargv (main.c:32)
==7309==    by 0x400CD4: parse_file (main.c:120)
==7309==    by 0x400DFF: main (main.c:172)
==7309== 
==7309== LEAK SUMMARY:
==7309==    definitely lost: 196 bytes in 3 blocks
==7309==    indirectly lost: 0 bytes in 0 blocks
==7309==      possibly lost: 0 bytes in 0 blocks
==7309==    still reachable: 888 bytes in 3 blocks
==7309==         suppressed: 0 bytes in 0 blocks
==7309== Reachable blocks (those to which a pointer was found) are not shown.
==7309== To see them, rerun with: --leak-check=full --show-reachable=yes
==7309== 
==7309== For counts of detected and suppressed errors, rerun with: -v
==7309== Use --track-origins=yes to see where uninitialised values come from
==7309== ERROR SUMMARY: 7 errors from 6 contexts (suppressed: 2 from 2)
Segmentation fault (core dumped)

推荐答案

您在 makeargv 中的 argvp 变量是一个指针数组,但是当您为其分配内存时您使用 sizeof(int)(在64位系统上仅为4个字节,而指针为8个字节).

Your argvp variable in makeargv is an array of pointers, but when you allocate he memory for it you use sizeof(int) which will only be four bytes on a 64 bit system, while pointers will be 8 bytes.

结果,您写的内容超出了数组的末尾,这就是为什么它报告您在20字节的块的偏移量16处写入了8个字节的原因,因此,它与块的末尾重叠了4个字节.

As a result you write beyond the end of the array - that's why it reports you writing 8 bytes at offset 16 of a 20 byte block, which therefore overlaps the end of the block by 4 bytes.

在分配 argvp 数组时,使用 sizeof(char *)获得正确的指针大小.

Use sizeof(char *) to get the correct size of a pointer when allocating the argvp array.

这篇关于无效写入大小为8的C Valgrind,字符串数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆