【问题标题】:getting characters from keyboard (memory allocation)从键盘获取字符(内存分配)
【发布时间】:2026-01-12 13:35:01
【问题描述】:

我想编写一个程序,从字符串中删除任何单词(用户可以键入该单词)。程序有效,但 valgind 给了我一些错误信息:

==3009== Command: ./remove3 infile
==3009== 
Type word that you want to remove from the file:
go
==3009== Invalid write of size 1
==3009==    at 0x4009CD: main (remove3.c:74)
==3009==  Address 0x51f1041 is 0 bytes after a block of size 1 alloc'd
==3009==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3009==    by 0x400947: main (remove3.c:45)
==3009== 
==3009== Invalid read of size 1
==3009==    at 0x400AE6: DELTEword (remove3.c:115)
==3009==    by 0x400A39: main (remove3.c:90)
==3009==  Address 0x51f1041 is 0 bytes after a block of size 1 alloc'd
==3009==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3009==    by 0x400947: main (remove3.c:45)
==3009== 
==3009== Invalid read of size 1
==3009==    at 0x400B16: DELTEword (remove3.c:118)
==3009==    by 0x400A39: main (remove3.c:90)
==3009==  Address 0x51f1041 is 0 bytes after a block of size 1 alloc'd
==3009==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3009==    by 0x400947: main (remove3.c:45)
==3009== 
That  Katharina and Petruchio should be married,
And yet we hear not of our son-in-law.
What will  be said? what mockery will it be,
To what bridegroom when the priest attends 
To speak the  ceremonial rites of marriage!
What says Lucentio to this shame of ours?
 ==3009== 
==3009== HEAP SUMMARY:
==3009==     in use at exit: 1 bytes in 1 blocks
==3009==   total heap usage: 50 allocs, 49 frees, 1,181 bytes allocated
==3009== 
==3009== LEAK SUMMARY:
==3009==    definitely lost: 1 bytes in 1 blocks
==3009==    indirectly lost: 0 bytes in 0 blocks
==3009==      possibly lost: 0 bytes in 0 blocks
==3009==    still reachable: 0 bytes in 0 blocks
==3009==         suppressed: 0 bytes in 0 blocks
==3009== Rerun with --leak-check=full to see details of leaked memory
==3009== 
==3009== For counts of detected and suppressed errors, rerun with: -v
==3009== ERROR SUMMARY: 95 errors from 3 contexts (suppressed: 2 from 2)

我也想问一下主体。我不完全确定我从键盘获取字符的方式是否正确,例如:当我输入“go”时一切正常,但无法删除“To”一词,为什么?

这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define CHUNK 12

char *getWord(FILE *infile);
int DELTEword(char *word, char *KEYword);

char *getWord(FILE *infile)
{
    int length, cursor = 0, c;
    char *word, *word2;

    word = (char*)malloc(sizeof(char)*CHUNK);
    if(word == NULL) return NULL;

    length = CHUNK;

        while((c = getc(infile)) != ' ' && !feof(infile))
        {
            word[cursor] = c;
            cursor++;

            if(cursor >= length)
            {
                length += CHUNK;
                word2 = (char*)realloc(word, length*sizeof(char));
                if(word2 == NULL)
                {
                    free(word);
                    return NULL;
                }
                else word = word2;
            }
        }

    word[cursor] = '\0';
    return word;
}

int main(int argc, char *argv[])
{
    char *word, c, *keyWord = (char*)malloc(sizeof(char));
    FILE *infile;
    int length;
    int size = 20;

    if(argc != 2)
    {
        printf("\nMissing arguments.\n");
        abort();
    }

    if(keyWord == NULL) return 0;

    printf("Type word that you want to remove from the file:\n");

    length = 0;

    while(1)
    {
        if(length == size)
        {
            keyWord = (char*)realloc(keyWord, size + 10);
            size += 10;
        }

        c = getchar();

        if(c == '\n') break;

        keyWord[length] = c;
        length++;
    }

    infile = fopen(argv[1], "r");
    if(infile != NULL)
    {
        while(!feof(infile))
        {
            word = getWord(infile);
            if(word == NULL)
            {
                free(word);
                break;
            }

            if(DELTEword(word, keyWord) == 1)
            {
                printf(word, infile);
                printf(" ");
                free(word);
            }
        }
    }
    else
    {
        printf("It is impossible to open the infile\n");
        abort();
    }

    fclose(infile);
    return 0;
}

int DELTEword(char *word, char *KEYword)
{
    int i, k = 0, l = 0, length;
    char *ptr;

    if(word != NULL)
    {
        length = strlen(KEYword);
        for(i = 0; word[i] != '\0'; i++)
        {
            if(word[i] == KEYword[k])
            {
                l++;
                k++;
            }
            else break;

            if(l == length)
            {
                ptr = &word[i];
                memmove((ptr - length) + 1, ptr + 1, strlen((ptr - length) + 1));
                l = 0;
                k = 0;
            }
        }
        return 1;
    }
    else return 0;
 }

感谢您的帮助。

【问题讨论】:

    标签: c


    【解决方案1】:

    引用 Valgrind 记录的无效写入/读取:

    您分配 1 个字节并将size 设置为20

    char *word, c, *keyWord = (char*)malloc(sizeof(char));
    ...
    int size = 20;
    

    这应该以某种方式链接,例如:

    int size = 20;
    char *word, c, *keyWord = malloc(size * sizeof(*keyWord));
    

    此外,您似乎缺少为“字符串”的0-terminator 分配空间。在 C 中,“字符串”是字符数组,其最后一个有效字符由后面的 NUL 字符表示。

    所以你总是需要再分配一个然后“字符串”应该能够容纳的最大字符数。


    顺便说一句:在 C 中不需要强制转换 malloc/calloc/realloc,也不推荐:https://*.com/a/605858/694576

    【讨论】:

      最近更新 更多