【问题标题】:Assertion in malloc.c:2453malloc.c:2453 中的断言
【发布时间】:2012-04-25 03:50:11
【问题描述】:

我有以下程序尝试对字符串进行标记(基于空格)并将其写入 char ** 数组。

#include <stdio.h>
#include <stdlib.h>

#define len 180

void tokenize(char *str, char **tokens)
{
    int l = 0, index = 0;
    int i = 0;
    int str_i;
    int tok_i;

    while(*str) {
        if (*str == ' ') {
            tokens[i] = malloc(sizeof(char) * l+1);
            if (tokens[i] == NULL) return;

            tok_i = 0;           
            for (str_i=index-len ; str_i<index ; str_i++) {
                tokens[i][tok_i] = str[str_i];
                tok_i++;
            }

            tokens[i][tok_i] = '\0';
            tokens[i++] = NULL;
            l = 0;
            index++;
        }
        str++;
        l++;
        index++;
    }       

    return;         
}

int main()
{
    char str[len] = "this is a test string";
    char **tokens = malloc(100 * sizeof(char *));

    if (str == NULL || tokens == NULL)
        return 1;

    printf("input string: %s\n", str);
    tokenize(str, tokens);

    return 0;
}

上面的程序编译得很好,但是在执行的时候,我在malloc.c得到了如下断言

$ gcc -ggdb -Wall prog.c 
$ ./a.out 
input string: this is a test string
a.out: malloc.c:2453: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
Aborted (core dumped)
$ 

堆栈跟踪显示如下:

(gdb) bt
#0  0x0000003b28036285 in raise () from /lib64/libc.so.6
#1  0x0000003b28037b9b in abort () from /lib64/libc.so.6
#2  0x0000003b2807d37d in __malloc_assert () from /lib64/libc.so.6
#3  0x0000003b28080c37 in _int_malloc () from /lib64/libc.so.6
#4  0x0000003b28082595 in malloc () from /lib64/libc.so.6
#5  0x000000000040055f in tokenize (str=0x7fffffffe017 " a test string", tokens=0x601010) at prog.c:15
#6  0x00000000004006de in main () at prog.c:46
(gdb) 

我该如何调试呢?任何想法将不胜感激。

【问题讨论】:

  • 我的 C 太生锈了,如果不坐在这里盯着它看 20 分钟,我无法给你任何有用的建议,但我可以立即告诉你,你忘记释放你的令牌指针,所以,这个程序泄漏内存(虽然不是很多),并且因为大概这是一个家庭作业(否则你真的应该只使用 strtok),这将花费你的积分。 :)

标签: c arrays malloc


【解决方案1】:

在你的 for 循环中

for (str_i=index-len ; str_i<index ; str_i++)

str_i 是一个负数。

【讨论】:

    【解决方案2】:
    for (str_i=index-len ; str_i<index ; str_i++) {
            tokens[i][tok_i] = str[str_i];
            tok_i++;
    }
    
    tokens[i][tok_i] = '\0';
    

    tokens[i][tok_i] 中至少有一个在分配的内存之外,因此您最终会破坏malloc 的内部信息。之后,hilarity ensues

    str_i 初始化也很有趣,因为第一次迭代时它将是 -180。

    【讨论】:

      【解决方案3】:

      是的,在@cnicutar 和@spicavigo 的建议下,我将代码更改如下,效果很好。

      #include <stdio.h>
      #include <stdlib.h>
      
      #define str_len 180
      
      void tokenize(char *str, char **tokens)
      {
          int length = 0, index = 0;
          int i = 0;
          int str_i;
          int tok_i;
      
          while(str[length]) {
              if (str[length] == ' ') {
                  /* this charecter is a space, so skip it! */
                  length++;
                  index++;
      
                  tokens[i] = malloc(sizeof(char) * (index+1));
      
                  tok_i = 0;           
                  for (str_i=length-index ; str_i<length; str_i++) {
                      tokens[i][tok_i] = str[str_i];
                      tok_i++;
                  }
      
                  tokens[i][tok_i] = '\0';
                  i++;
                  index = 0;
              }
              length++;
              index++;
          }       
      
          /* copy the last word in the string */
          tokens[i] = malloc(sizeof(char) * index);
          tok_i = 0;           
          for (str_i=length-index ; str_i<length; str_i++) {
              tokens[i][tok_i] = str[str_i];
              tok_i++;
          }
          tokens[i][tok_i] = '\0';
          tokens[i++] = NULL;
      
          return;         
      }
      
      int main()
      {
          char *str = malloc(str_len * sizeof(char));
          char **tokens = malloc(100 * sizeof(char *));
          int i = 0;
      
          if (str == NULL || tokens == NULL)
              return 1;
      
          gets(str);
          printf("input string: %s\n", str);
          tokenize(str, tokens);
      
          while(tokens[i] != NULL) {
              printf("%d - %s \n", i, tokens[i]);
              i++;
          }
      
          while(tokens[i])
              free(tokens[i]);
          free(tokens);
          free(str);
      
          return 0;
      }
      

      【讨论】:

      • 它可能会工作,但tokens[i] = malloc(sizeof(char) * index); 没有分配足够的内存,tokens[i][tok_i] = '\0'; 行将始终是缓冲区溢出。例如,当index为1,length为1时,会malloc 1字节,复制1字节,然后将'\0'写入tokens[i][1]
      • 另外,indexlength 是误导性名称,让人难以理解。 index 是非空格标记的countlength 是源数组中的index
      猜你喜欢
      • 2021-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多