我试图返回一个字符串数组,当我复制字符串时,当它通过第四个索引时,发生了一些奇怪的事情。例如,当它在前3次循环时,将其存储为“ the”,但随后突然被重写,但它写入的下一个索引恰好[index 5]。你们能发现任何问题吗,因为我很困惑。

#include <stdlib.h>
#include <stdio.h>
#include "hash.h"
#include <string.h>
#define MAX 200
#define TERMINATE "asdfghjkl"

int createTable(int numFiles, char** files, char** stopList)
{
  printf("stepped into create table\n");
  FILE* fp1;
  char oneWord[100];

  HashTable hash = InitializeTable(900000);
  int index = 2;

  while(numFiles >0) {
    fp1 = fopen(files[index++], "r");
    while(fscanf(fp1, "%s", oneWord)!=EOF){
      Insert(oneWord, hash, stopList);
    }
  numFiles--;
  }
  return 0;
}

char** createStopList(char* stopL)
{
  FILE* fp1;
  fp1 = fopen(stopL, "r");
  char oneWord[100];
  int i = 0;
  char* stopList[MAX];
  while(fscanf(fp1, "%s", oneWord)!=EOF){
    stopList[i] = (char*)malloc(sizeof(oneWord));
    strcpy(stopList[i++], oneWord);
  }
  stopList[i] = (char*)malloc(sizeof(char*));
  strcpy(stopList[i], TERMINATE);

  char** strings = stopList;
  char** returnList = malloc(sizeof(strings));
  i=0;
  while(strcmp(strings[i], TERMINATE)!=0){
    returnList[i] = malloc(sizeof(char*));
    strcpy(returnList[i], strings[i]);
    i++;
  }
  returnList[i] = (char*)malloc(sizeof(char*));
  strcpy(returnList[i], TERMINATE);
  return returnList;
}

int main(int argc, char** argv)
{
  printf("start of prg\n");
  char** stopList= createStopList(argv[1]);
  createTable(argc-2, argv, stopList);
  return 0;
}

最佳答案

此代码导致缓冲区溢出:

#define TERMINATE "asdfghjkl"
// ...
returnList[i] = (char*)malloc(sizeof(char*));
strcpy(returnList[i], TERMINATE);


TERMINATE的长度为10,但是sizeof(char*)可能小于10

要解决这个问题:

returnList[i] = malloc( sizeof TERMINATE );
strcpy(returnList[i], TERMINATE);


您的评论建议您改用strdup(该功能不在Standard C中,但通常提供)。

这也是完全fubar'd:

char** strings = stopList;
char** returnList = malloc(sizeof(strings));
// ...
returnList[i] = malloc(sizeof(char*));


sizeof(strings)sizeof(char **)相同,可能是48,但是一旦i进入1,您就继续写越过该数组的末尾!这可能是您出现症状的原因。

我认为您可能对sizeof的功能有误解。它告诉您使用了多少字节来存储变量(如果该变量是指针,则不指向该变量指向的位置有多少字节)。

想必您的意思是:

returnList = malloc( (i+1) * sizeof *returnList );


这为索引returnList[0]returnList[i]提供了足够的指针。

此后的代码设计不当,您有不必要的代码重复。将while循环更改为do...while,然后最后一次迭代将为您复制TERMINATE,而无需为其编写额外的代码。

在同一功能的早期,此行很差:

while(fscanf(fp1, "%s", oneWord)!=EOF){


您应该防止输入溢出。同样,您也永远不会检查i是否超过MAX。并可以进行其他改进。无需将TERMINATE复制到stopList中,只需保存i,并在TERMINATE的末尾写returnList

最终,您似乎毫无意义地存储和复制了数组,而不是仅仅动态地分配了数组。哦,您的malloc有疣。

将所有这些更改放在一起:

char **createStopList(char const *stopL)
{
    FILE* fp1;
    fp1 = fopen(stopL, "r");
    char oneWord[100];
    size_t i;
    char **stopList;

    if ( !fp1 )
        return NULL;

    stopList = malloc(MAX * sizeof *stopList);
    if ( !stopList )
         exit(EXIT_FAILURE);

    for (i = 0; i < MAX - 1 && fscanf(fp1, "%99s", oneWord) == 1; ++i)
    {
        stopList[i] = malloc( strlen(oneWord) + 1);
        if ( !stopList[i] )
            exit(EXIT_FAILURE);
        strcpy(stopList[i], oneWord);
    }

    stopList[i] = malloc(sizeof TERMINATE);
    strcpy(returnList[i], TERMINATE);

// (optional) free entries you didn't use in the list
    stopList = realloc(stopList, (i+1) * sizeof *returnList);
    if ( !stopList )
        exit(EXIT_FAILURE);

    return stopList;
}

关于c - 我的returnList [0]被重写为@ 5',我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23330069/

10-11 01:10