【问题标题】:Segmentation Fault error in method C programming方法 C 编程中的分段错误错误
【发布时间】:2015-01-16 19:40:45
【问题描述】:

下面是我创建的名为 inputReader 的方法的代码,它从文本文件读取输入并将其复制到结构 wordz 并从该结构中检索 3 个最常用的单词,如下所示。

我试图将所有 3 个单词作为一个指针连接起来,这样我就可以将它返回给 main 方法,但是每当我使用任何方法来处理 w1、w2、w3 时,它都会复制到一个新的结构或数组或指针,我总是收到此错误“分段错误(核心转储)”

知道为什么会发生这种情况或我可以如何解决它吗?

结构代码:

#define maxLetters 101

typedef struct {
  char word[maxLetters];
  int  freq;
} WordArray; //struct type

代码:

char * w1; // most frequent word 
char * w2; // second most frequent word
char * w3; // third most frequent word

// finds w1
for(j = 0; j < uniqueWords; j++)
  if(wordz[j].freq == freqz[uniqueWords-2]+1)//excludes whitespace frequency
     w1 = wordz[j].word;

// finds w2
for(j = 0; j < uniqueWords; j++)
  if(wordz[j].freq == freqz[uniqueWords-3]+1)//excludes whitespace frequency
     w2 = wordz[j].word;

// finds w3
for(j = 0; j < uniqueWords; j++)
  if(wordz[j].freq == freqz[uniqueWords-4]+1)//excludes whitespace frequency
     w3 = wordz[j].word;

 char *p;

 // if i dont include strcat methods the method runs fine and outputs fine
 strcat(p, w1);  // once this operation is executed i get the error
 strcat(p, " ");
 strcat(p, w2);
 strcat(p, " ");
 strcat(p, w3);

【问题讨论】:

  • 无法保证最大频率字数为 size-2,size-3, size-4。 (也没有看到任何迹象表明 size-1 实际上是空白频率计数器。)建议在检查第二个和第三个最常见的单词并在已提取作品的偏移量,因此那些已选择的单词将被忽略。
  • 除非这个数组:freq[] 是一个排序的频率数组,这可能不起作用,可能不起作用,并且当最频繁的字数是重复值时不起作用,因为它总是为每个条目选择相同的单词
  • 这个指针'p'需要定义一些内存区域来接收单词。建议类似:'char *p = malloc(3*(maxLetters)+4));'当然,检查 malloc 的返回值以确保操作成功。 +4 插入 3 个空格 + 最后的 nul 字符。注意:按照惯例,#define 名称是这样写的:MAX_LETTERS 全部大写,单词用下划线分隔

标签: c linux struct segmentation-fault


【解决方案1】:

您正在尝试连接到未初始化的指针。将内存分配给“p”。

char *p = malloc(size)

【讨论】:

  • 当人们向我展示使用 strcat 的代码时,提醒他们使用 strncat 总是很有帮助。它是软件中大量安全问题的根源!
  • 还有if (p == 0) { ...error... }p[0] = '\0';在尝试使用strcat()之前——malloc()返回的内存并不总是归零。
  • strcat()指向一个通过malloc()初始化的指针是个坏主意,因为引用的内存没有被初始化。 如果这样做了,对这个指针的第一个操作应该是strcpy()
  • 另外,这种错误通常很容易通过在 gdb 下运行,然后执行 bt(回溯)命令来定位。
【解决方案2】:

最好仔细阅读 strcat 的文档以检查您是否正确使用它。例如,您可以在这里查看http://man7.org/linux/man-pages/man3/strcat.3.html。在 stackoverflow 上也有很多类似问题的答案,您会发现它们很有帮助:

但是,为了避免您的痛苦,错误是因为没有为结果字符串p 分配任何空间。 strcat 不像在 C# 或其他语言中那样在 C 中执行此操作。

你需要:

char p[maxletters];

更好的是,您应该使用带有大小限制的 strncpy 来防止内存损坏:

strncpy(p, w1, maxletters);

【讨论】:

  • 或者干脆用strcpy()代替第一个strcat()
  • 是的。我的错误——我应该注意到的。但同样,这也应该是 strncpy!
  • @alk。修补了我对我的意图的回答,这就是你注意到的!拍了我的手。应该知道的更好。
  • 使用 strncpy() 但仍可能导致 p 未指向有效的 C-"sting",因为 0-terminator 可能会错过。
【解决方案3】:

导致您的问题的根本原因是 p 没有指向任何地方,因此尝试将数据复制到它会调用臭名昭著的未定义行为。

所以分配一些内存给p,无论是从堆中还是从栈中。

要从堆中获取它:

char * p = malloc(some_size);

当尝试将strcat() 数据指向此指针时,请注意strcat() 期望它的第一个参数已经指向一个有效的C-“字符串”,即0-终止的char 数组,以它可以连接第二个参数所指向的内容。

要注意这一点,请确保p 指向的数据至少将其第一个字节设置为0

p[0] = '\0';

如果不是所有字节:

memset(p, 0, some_size);

如果选择后者,您可能还想这样做:

char * p = calloc(some_size, sizeof *p);

因为calloc()malloc() 的作用相同,并且额外初始化了所有使用0s 分配的内存。

如果你觉得初始化很费力,那么你不能开始使用strcat() 进行连接,而是从strcpy() 开始,这依赖于它的第一个参数指向一个有效的 C- “字符串”,但只是将其第二个参数所指向的内容复制到其第一个参数所指向的位置。

chart * p = malloc(some_size);
strcpy(p, w1);  
strcat(p, " ");
...

最后:

  • 如果不再需要内存,不要忘记在p 上调用free(),以避免内存泄漏。

  • 在使用之前还要检查内存分配的结果,即检查malloc/calloc()NULL的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-07
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-09
    • 2011-05-07
    相关资源
    最近更新 更多