【问题标题】:C - Valgrind "Invalid read/write of size 1" errors while strcpy/strlenC - 在 strcpy/strlen 时,Valgrind 出现“大小为 1 的无效读/写”错误
【发布时间】:2023-12-13 11:24:01
【问题描述】:

我遇到了 seg.faults 的问题。该程序运行良好,但对于少数未知字符串会导致分段错误。我用 Valgrind 运行程序,它报告“大小为 1 的无效读/写”,主要是问题与 strcpy 和 strlen 有关。

==5623== ERROR SUMMARY: 12 errors from 4 contexts (suppressed: 2 from 2)
==5623== 
==5623== 1 errors in context 1 of 4:
==5623== Invalid write of size 1
==5623==    at 0x4C2D812: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5623==    by 0x400955: sameWords (main.c:62)
==5623==    by 0x400A6F: main (main.c:85)
==5623==  Address 0x51fd093 is 0 bytes after a block of size 3 alloc'd
==5623==    at 0x4C2CD7B: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5623==    by 0x40092B: sameWords (main.c:59)
==5623==    by 0x400A6F: main (main.c:85)
==5623== 
==5623== 
==5623== 1 errors in context 2 of 4:
==5623== Invalid write of size 1
==5623==    at 0x4C2D812: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5623==    by 0x400942: sameWords (main.c:61)
==5623==    by 0x400A6F: main (main.c:85)
==5623==  Address 0x51fd045 is 0 bytes after a block of size 5 alloc'd
==5623==    at 0x4C2CD7B: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5623==    by 0x400913: sameWords (main.c:58)
==5623==    by 0x400A6F: main (main.c:85)
==5623== 
==5623== 
==5623== 4 errors in context 3 of 4:
==5623== Invalid read of size 1
==5623==    at 0x4C2D7B4: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5623==    by 0x4009EC: sameWords (main.c:70)
==5623==    by 0x400A6F: main (main.c:85)
==5623==  Address 0x51fd093 is 0 bytes after a block of size 3 alloc'd
==5623==    at 0x4C2CD7B: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5623==    by 0x40092B: sameWords (main.c:59)
==5623==    by 0x400A6F: main (main.c:85)
==5623== 
==5623== 
==5623== 6 errors in context 4 of 4:
==5623== Invalid read of size 1
==5623==    at 0x4C2D7B4: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5623==    by 0x40099E: sameWords (main.c:65)
==5623==    by 0x400A6F: main (main.c:85)
==5623==  Address 0x51fd045 is 0 bytes after a block of size 5 alloc'd
==5623==    at 0x4C2CD7B: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5623==    by 0x400913: sameWords (main.c:58)
==5623==    by 0x400A6F: main (main.c:85)
==5623== 
--5623-- 
--5623-- used_suppression:      2 dl-hack3-cond-1
==5623== 
==5623== ERROR SUMMARY: 12 errors from 4 contexts (suppressed: 2 from 2)

程序应该找出两个字符串是否由相同的单词组成(并忽略不同大小的字母)。对于我的代码的出现,我感到非常抱歉,我对编程很陌生,并且仍在努力学习如何编写可以理解的代码,所以我将简要解释正在做什么(至少我是这么认为的)在哪里。 WordInString 函数从一个字符串中获取一个又一个单词,然后在另一个字符串中找到它。这个词被复制到动态分配的数组中,因为我不知道这些词可能有多长。然后在函数 sameWords 中,我将字符串复制到新数组中,这样我就可以将所有单词转换为小写字母,然后调用函数 WordInString 来搜索字符串中的单词。我的主要功能是我只用 2 个字符串调用 sameWords。

代码看起来像这样。再次为糟糕的安排感到抱歉。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>


int WordInString(const char *a, const char *b)
{
    /* Selecting words one after another and finding the word in another strin.
    Dynamic allocation of word string, because words lengths are unknown.*/
    char * word=NULL;
    int previous = 0;
    int length=0;
    int wordlength=0;
    int i;

    if((strlen(a)==0) && (strlen(b)==0))
        {
        return 1;
        }

    i=0;
    while(1)
        {
        if (i>=wordlength) {wordlength+=250; word=(char*) malloc(wordlength*sizeof(char));}
        if(isalpha(a[i]))
            {
            if(!isalpha(previous))
                {
                length=0;
                }
            if(length<80) word[length++] = tolower(a[i]);
            }
            else
                {
                if(length>0)
                    {
                    word[length] = '\0';
                    if(strstr(b, word)==NULL)
                        {
                        return 0;
                        }
                    length=0;
                    }
                }
                if(a[i] == '\0') {break;}
                previous=tolower(a[i++]);
        }
    free(word);
    return 1;
}

int sameWords( const char * a, const char * b)
{
    int i=0, j=0;
    char * array1=(char*) malloc(strlen(a)*sizeof(char));
    char * array2=(char*) malloc(strlen(b)*sizeof(char));
    /* copy a and b strings to new string, that are not cons, so they can be changed      tolower */
    strcpy(array1, a);
    strcpy(array2, b);

    /* convert strings to lower letters  */
    for(i=0; i<strlen(array1); i++)
        {
        array1[i]=tolower(array1[i]);
        }
    for(j=0; j<strlen(array2); j++)
        {
        array2[j]=tolower(array2[j]);
        }
    /* calling WordInString to compare */
    if (WordInString(a, array2)==0) {return 0;}
    if (WordInString(b, array1)==0) {return 0;}
    free(array1);
    free(array2);
    return 1;
}


int main ( int argc, char * argv [] )
{
    int res;
    res=(sameWords("This is a string", "This string is a string"));
    return 0;
}


我会非常感谢你的帮助。我试图查找它,但无法弄清楚。

【问题讨论】:

  • malloc(strlen(a)*sizeof(char)); Size +1 需要字符串的结尾'\0'
  • Please don't cast the return value of malloc() in C。此外,按sizeof (char) 缩放从来都不好,它只是 1,所以它只会增加混乱。
  • 所以我应该做 malloc((strlen(a)+1)*sizeof(char)); ?而不是 sizeof,你会建议什么?我唯一能想到的就是用一些计数器遍历两个字符串,然后将计数器放在那里而不是 sizeof。
  • 如果:if (WordInString(a, array2)==0) {return 0;} 不会释放 array1 和 array2。所以你会有泄漏
  • 但是当我通过 Valgrind 运行它时,它说一切都被释放了。我释放了这两个函数中的所有数组。

标签: c string malloc valgrind


【解决方案1】:

malloc(strlen(a)*sizeof(char)); 大小 +1 需要以 '\0' 结尾的字符串 - BLUEPIXY

【讨论】:

    最近更新 更多