繁体   English   中英

为什么此C程序在此位置出现段错误?

[英]Why is this C program segfaulting at this location?

我正在开发一个C语言程序,该程序基本上可以使用一个句子并计算每个单词出现在其中的次数。 我制作了一个精简版,可以准确地再现问题。

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

typedef struct testStrut{ 
    char * string; 
    int uses; 
}word; 

void grow(); 

int main(){
    int i; 
    int count = 1; 
    word ** words; 

    words = (word **) malloc(count * sizeof(word *)); 
    words[0] = (word *) malloc(sizeof(word)); 

    for(i = 0; i < 10; i++){
        printf("Re-looping i: %d \n", i); 
        printf("words[0]->string = %s \n", words[0]->string); 
        grow("TEST", words, &count); 
    }

    printf("Done."); 
    return 0; 
}

void grow(char * str, word ** words, int * count){
    word ** tmp; 

    tmp = realloc(words, (*count) * sizeof(word *)); 

    if(tmp){
        tmp[(*count)-1] = malloc(sizeof(word)); 
        tmp[(*count)-1]->string = malloc(strlen(str)+1); /*+1 for null terminator as pointed out */  
        strcpy(tmp[(*count)-1]->string, str); 
        tmp[(*count)-1]->uses = 1;     
        words = tmp; 
        (*count)++; 
    } else{
        printf("Failure to allocate. \n"); 
        exit(0); 
    }
    printf("Count: %d and word[0] %s \n", (*count), str); 
}

以及运行的输出:

Re-looping i: 0
words[0]->string = (null)
Count: 2 and word[0] TEST
Re-looping i: 1
words[0]->string = TEST
Count: 3 and word[0] TEST
Re-looping i: 2
words[0]->string = TEST
Count: 4 and word[0] TEST
Re-looping i: 3
words[0]->string = TEST
Count: 5 and word[0] TEST            /*Prints it fine? */ 
Re-looping i: 4
Segmentation fault (core dumped)     /*Suddenly unable to print it? */ 

我不明白为什么在结束增长功能和重新执行循环之间,单词[0]-> str的值突然丢失。 有什么我想念的吗?

[我确实知道我应该释放我分配的任何东西。我也意识到我的方法原型不是正确的方法,但我只是想制作一个演示我问题的快速程序]

在for循环的第一次迭代中,下一行正在访问未初始化的内存。

printf("words[0]->string = %s \n", words[0]->string);

您还声明了

void grow();

但实际签名即

void grow(char * str, word ** words, int * count)

您首先需要在该行之前调用grow 您还要重新realloc并假设main中的指针words指向原始指针。

尝试这个。 我简化了一点...

#include <assert.h>
#include <stdio.h>
#include <stdlib.h> 
#include <string.h>
typedef struct testStrut{ 
  char * string; 
  int    uses; 
} word; 

void grow(const char *str, word *words, int count); 

int main(){
  int i;  
  word * words; 
  printf("sizeof word == %zu\n", sizeof(word));
  assert(sizeof(word) == 16);
  words    = malloc(sizeof(word)); 
  for(i = 0; i < 10; i++){
    printf("Re-looping i: %d \n", i); 
    grow("TEST", words, i); 
    printf("words[0]->string = %s \n", words[0].string); 
  }
  printf("Done."); 
  return 0;  
}
void grow(const char * str, word *words, int count){
  word ** tmp; 
  int idx = count - 1;
  printf("size == %zu\n", count * sizeof(word));
  tmp = realloc(words, count * sizeof(word)); 
  size_t str_len = strlen(str); 
  if(tmp != NULL) {
    tmp[idx]         = malloc(sizeof(word*)); 
    tmp[idx]->string = malloc(str_len + 1); 
    strcpy(tmp[idx]->string, str); 
    tmp[idx]->string[4] = '\0';
    tmp[idx]->uses = 1;
  } else{
    printf("Failure to allocate. \n");
    exit(0);
  }
  printf("Count: %d and word[0] %s \n", count, str);
}

问题在这里:

words = tmp; 

该语句在函数外部无效。

由于realloc可能会(也可能不会)返回指向另一个内存位置的新指针,因此您的代码在崩溃前可能会工作几次。

您应该使用单词***而不是单词**参数,或者仅返回新指针:

word** grow(char * str, word ** words, int * count){
    word ** tmp; 

    tmp = realloc(words, (*count) * sizeof(word *)); 

    if(tmp){
        tmp[(*count)-1] = malloc(sizeof(word)); 
        tmp[(*count)-1]->string = malloc(strlen(str)+1); /*+1 for null terminator as pointed out */  
        strcpy(tmp[(*count)-1]->string, str); 
        tmp[(*count)-1]->uses = 1;   
        (*count)++; 
    } else{
        printf("Failure to allocate. \n"); 
        exit(0); 
    }
    printf("Count: %d and word[0] %s \n", (*count), str); 
    return tmp;
}

并这样称呼:

words = grow("TEST", words, &count); 

暂无
暂无

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

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