我试图返回一个字符串数组,当我复制字符串时,当它通过第四个索引时,发生了一些奇怪的事情。例如,当它在前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 **)
相同,可能是4
或8
,但是一旦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/