C strcpy_s -缓冲区太小和0错误

时间:2022-11-10 17:02:57

I have buffer problem on this line strcpy_s(*(pWords + word_count), word_length, pWord); I'm trying to read a file from argv[1] and print out every single word in that file and their occurrence, but I can't figure out whats wrong..?!?

这行strcpy_s(*(pWords + word_count)、word_length、pWord)存在缓冲区问题;我试着从argv[1]读取一个文件,并打印出文件中的每个单词和它们的出现,但是我不知道哪里出错了。

int main(int argc, char* argv[])
{
    char *delimiters = argv[2];                     // Prose delimiters
    char buf[BUF_LEN];                                       // Buffer for a line of keyboard input
    size_t str_size = INIT_STR_EXT;                          // Current memory to store prose
    char*  filePath = argv[1];
    FILE *fP ;
    char* pStr = malloc(str_size);                           // Pointer to prose to be tokenized
    *pStr = '\0';                                            // Set 1st character to null
    fopen_s(&fP, filePath, "r");
    fread(buf, BUF_LEN, 10, fP);





    size_t maxWords = 10;                                     // Current maximum word count
    int word_count = 0;                                       // Current word count
    size_t word_length = 0;                                   // Current word length
    char** pWords = calloc(maxWords, sizeof(char*));          // Stores pointers to the words
    int* pnWord = calloc(maxWords, sizeof(int));              // Stores count for each word

    size_t str_len = strnlen_s(buf, BUF_LEN);                // Length used by strtok_s()
    char* ptr = NULL;                                          // Pointer used by strtok_s()
    char* pWord = strtok_s(buf, delimiters, &ptr);  // Find 1st word

    if (!pWord)
    {
        printf("No words found. Ending program.\n");
        return 1;
    }

    bool new_word = true;                                     // False for an existing word
    while (pWord)
    {
        // Check for existing word
        for (int i = 0; i < word_count; ++i)
        if (strcmp(*(pWords + i), pWord) == 0)
        {
            ++*(pnWord + i);
            new_word = false;
            break;
        }

        if (new_word)                                            // Not NULL if new word
        {
            //Check for sufficient memory
            if (word_count == maxWords)
            { // Get more space for pointers to words
                maxWords += WORDS_INCR;
                pWords = realloc(pWords, maxWords*sizeof(char*));

                // Get more space for word counts
                pnWord = realloc(pnWord, maxWords*sizeof(int));
            }

            // Found a new word so get memory for it and copy it there
            word_length = ptr - pWord;      // Length of new word
            *(pWords + word_count) = malloc(word_length);         
            strcpy_s(*(pWords + word_count), word_length, pWord); // Copy to array
            *(pnWord + word_count++) = 1;                         // Increment word count
        }
        else
            new_word = true;                                      // Reset new word flag

        pWord = strtok_s(NULL, delimiters, &ptr);      // Find subsequent word
    }

3 个解决方案

#1


1  

There are two problems with this line:

这条线有两个问题:

fread(buf, BUF_LEN, 10, fP);

Firstly the buffer is too small by a factor of 10 as you read 10 elements.

首先,当您读取10个元素时,缓冲区太小了10倍。

Second, it does not read the file further than BUF_LEN (previously, *10).

其次,它不会比BUF_LEN(以前是*10)更深入地读取文件。

Also the code does not take care of newline chars, as I cannot pass that in argv[2] delimiter spec, even as " \\n".

同样,代码也不关心换行符,因为我不能在argv[2]分隔符规范中传递这一点,即使是“\\n”。

I suggest you replace fread() with a loop of fgets(), and redefine the word delimiters.

我建议您用fgets()循环替换fread(),并重新定义单词分隔符。

#define BUF_LEN 1000                        // plenty of room
...
char buf[BUF_LEN+1];                        // allow for 0 terminator
char delimiters[] = " \n\t";                // predefined
...
//size_t str_len = strnlen_s(buf, BUF_LEN); // unnecessary
while (fgets(buf, BUF_LEN, fP) != NULL) {   // new outer loop
    char* ptr = NULL;                       // carry on as you were
    ...
}

Next, as others commented, increase the string space allocation

接下来,正如其他人所评论的,增加字符串空间分配。

*(pWords + word_count) = malloc(word_length+1);

In addition, although you have used the "safe" string functions, you did not check argc or the result of any of fopen_s(), fread(), malloc(), calloc(), realloc(), nor have you closed the file or released memory.

此外,尽管您使用了“安全”字符串函数,但您没有检查argc或任何fopen_s()、fread()、malloc()、calloc()、realloc()的结果,也没有关闭文件或释放内存。

#2


2  

strcpy_s adds a null byte to the end of the string. You need to malloc(word_length+1).

strcpy_s在字符串的末尾添加一个空字节。你需要malloc(word_length + 1)。

#3


0  

Looks to me like you forgot to get an additional byte for the 0 character. Despite that: Instead of allocating a fixed buffer size for your file, you could get the filesize with fseek using SEEK_END and an offset of 0 to allocate that much memory+1 byte

在我看来,您似乎忘记为0字符获取额外的字节。尽管如此:与其为文件分配固定的缓冲区大小,不如使用SEEK_END使用fseek实现filesize,并使用一个0的偏移量来分配这么多的内存+1字节

#1


1  

There are two problems with this line:

这条线有两个问题:

fread(buf, BUF_LEN, 10, fP);

Firstly the buffer is too small by a factor of 10 as you read 10 elements.

首先,当您读取10个元素时,缓冲区太小了10倍。

Second, it does not read the file further than BUF_LEN (previously, *10).

其次,它不会比BUF_LEN(以前是*10)更深入地读取文件。

Also the code does not take care of newline chars, as I cannot pass that in argv[2] delimiter spec, even as " \\n".

同样,代码也不关心换行符,因为我不能在argv[2]分隔符规范中传递这一点,即使是“\\n”。

I suggest you replace fread() with a loop of fgets(), and redefine the word delimiters.

我建议您用fgets()循环替换fread(),并重新定义单词分隔符。

#define BUF_LEN 1000                        // plenty of room
...
char buf[BUF_LEN+1];                        // allow for 0 terminator
char delimiters[] = " \n\t";                // predefined
...
//size_t str_len = strnlen_s(buf, BUF_LEN); // unnecessary
while (fgets(buf, BUF_LEN, fP) != NULL) {   // new outer loop
    char* ptr = NULL;                       // carry on as you were
    ...
}

Next, as others commented, increase the string space allocation

接下来,正如其他人所评论的,增加字符串空间分配。

*(pWords + word_count) = malloc(word_length+1);

In addition, although you have used the "safe" string functions, you did not check argc or the result of any of fopen_s(), fread(), malloc(), calloc(), realloc(), nor have you closed the file or released memory.

此外,尽管您使用了“安全”字符串函数,但您没有检查argc或任何fopen_s()、fread()、malloc()、calloc()、realloc()的结果,也没有关闭文件或释放内存。

#2


2  

strcpy_s adds a null byte to the end of the string. You need to malloc(word_length+1).

strcpy_s在字符串的末尾添加一个空字节。你需要malloc(word_length + 1)。

#3


0  

Looks to me like you forgot to get an additional byte for the 0 character. Despite that: Instead of allocating a fixed buffer size for your file, you could get the filesize with fseek using SEEK_END and an offset of 0 to allocate that much memory+1 byte

在我看来,您似乎忘记为0字符获取额外的字节。尽管如此:与其为文件分配固定的缓冲区大小,不如使用SEEK_END使用fseek实现filesize,并使用一个0的偏移量来分配这么多的内存+1字节