简体   繁体   English

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

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

I'm working on making a C program that basically can take a sentence and count how many times each word appears in it. 我正在开发一个C语言程序,该程序基本上可以使用一个句子并计算每个单词出现在其中的次数。 I've made a stripped down version that reproduces the issue exactly. 我制作了一个精简版,可以准确地再现问题。

#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); 
}

As well as the output from a run: 以及运行的输出:

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? */ 

I'm not understanding why between ending the grow function and re-going through the loop the value of words[0]->str is suddenly lost. 我不明白为什么在结束增长功能和重新执行循环之间,单词[0]-> str的值突然丢失。 Is there something I'm missing? 有什么我想念的吗?

[I do know that I should be freeing anything I malloc.I also realize my method prototype isn't the correct one but I just wanted to make a quick program that demonstrated my issue] [我确实知道我应该释放我分配的任何东西。我也意识到我的方法原型不是正确的方法,但我只是想制作一个演示我问题的快速程序]

On the first iteration of the for loop the following line is accessing uninitialized memory. 在for循环的第一次迭代中,下一行正在访问未初始化的内存。

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

You have also declared 您还声明了

void grow();

but the actual signature ie 但实际签名即

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

You first need to call grow before that line ie. 您首先需要在该行之前调用grow You are also realloc and assuming that the pointer words in main points to the original pointer. 您还要重新realloc并假设main中的指针words指向原始指针。

Try this. 尝试这个。 I've simplified a little bit... 我简化了一点...

#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);
}

The problem is here : 问题在这里:

words = tmp; 

This statement has no effect outside of the function. 该语句在函数外部无效。

Since realloc may (or may not) return a new pointer to another memory location, you code may work a few times before crashing. 由于realloc可能会(也可能不会)返回指向另一个内存位置的新指针,因此您的代码在崩溃前可能会工作几次。

You should use a word*** instead of the word** parameter or simply return the new pointer: 您应该使用单词***而不是单词**参数,或者仅返回新指针:

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;
}

And call it this way: 并这样称呼:

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

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

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