c语言 - 如何修复似乎不适用的瓦尔格林德条件跳转错误?



我正在编写一个C程序,该程序将确定给定字符串是否为半字符(2个或更多回文的连接),虽然我的解决方案确实有效,但我不断获得Valgrind错误,这对我来说没有任何意义。我对C和valgrind相当陌生,虽然我大致理解错误的含义,但我不知道它们如何应用到我的代码中。

下面是我的代码:

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
// Function to check if a given string is a palindrome
int isPalindrome(char str[]) {
int len = strlen(str);
if (len == 1){return 0;}
int left = 0;
int right = len - 1;
while (right > left) {
if (str[left++] != str[right--]) {
return 0;
}
}
return 1;
}
bool is_semidrome(char *s) {
int len = strlen(s);
// If empty string, automatically not a semidrome
if(len == 0){return 0;}
// If palindrome, automatically a semidrome
if(isPalindrome(s)){return 1;}
// Initialize two arrays to check if a substring is a palindrome
char *palcheck, *palcheckrest;
for (int i = 1; i < len; i++){
// Go through the array until we find a char same as s[0] (potential palindrome)
if (s[0] == s[i]){
// make an array of the potential palindrome
palcheck = malloc((i+2)*sizeof(char));
palcheck = strncpy(palcheck, s, i+1);
palcheck[i+1] = '';
// if it is a palindrome, recursively check if the rest is a semidrome
if (isPalindrome(palcheck)){
// make a new substring with the rest of the string        
palcheckrest = malloc((len - i)*sizeof(char));
for (int j = 0; j < (len - i - 1); j++){
palcheckrest[j] = s[j+i+1];
}
palcheckrest[len - i] = '';
// if it is a semidrome, return true
if (is_semidrome(palcheckrest)){
free(palcheck);
free(palcheckrest);
return true;}
else{
free(palcheck);
free(palcheckrest);
// if i is the ending index and we still haven't found a potential palindrome, return false
if(i == len){
return false;}
// if i is not the ending index, keep checking
else{
free(palcheck);
free(palcheckrest);
continue;}
}}
else {
free(palcheck);
continue;}
}
}}

下面是valgrind错误:

Input:
popeye==152438== Memcheck, a memory error detector
==152438== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==152438== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==152438== Command: ./student_answer
==152438== 
==152438== Invalid write of size 1
==152438==    at 0x10A3CE: is_semidrome (semidrome.c:39)
==152438==    by 0x10A1EB: main (main.c:11)
==152438==  Address 0x4a73154 is 0 bytes after a block of size 4 alloc'd
==152438==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==152438==    by 0x10A377: is_semidrome (semidrome.c:35)
==152438==    by 0x10A1EB: main (main.c:11)
==152438== 
==152438== Conditional jump or move depends on uninitialised value(s)
==152438==    at 0x483EF58: strlen (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==152438==    by 0x10A2B4: is_semidrome (semidrome.c:23)
==152438==    by 0x10A3DC: is_semidrome (semidrome.c:40)
==152438==    by 0x10A1EB: main (main.c:11)
==152438== 
==152438== Conditional jump or move depends on uninitialised value(s)
==152438==    at 0x483EF58: strlen (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==152438==    by 0x10A230: isPalindrome (semidrome.c:9)
==152438==    by 0x10A2D3: is_semidrome (semidrome.c:25)
==152438==    by 0x10A3DC: is_semidrome (semidrome.c:40)
==152438==    by 0x10A1EB: main (main.c:11)
==152438== 
==152438== 
==152438== HEAP SUMMARY:
==152438==     in use at exit: 0 bytes in 0 blocks
==152438==   total heap usage: 5 allocs, 5 frees, 8,250 bytes allocated
==152438== 
==152438== All heap blocks were freed -- no leaks are possible
==152438== 
==152438== Use --track-origins=yes to see where uninitialised values come from
==152438== For lists of detected and suppressed errors, rerun with: -s
==152438== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

我知道我没有最有效或最优雅的解决方案,但目前的重点是了解如何修复Valgrind错误。

看看你的代码。Valgrind会告诉你哪里做错了。

==152438== Invalid write of size 1
==152438==    at 0x10A3CE: is_semidrome (semidrome.c:39)
==152438==    by 0x10A1EB: main (main.c:11)
==152438==  Address 0x4a73154 is 0 bytes after a block of size 4 alloc'd
==152438==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==152438==    by 0x10A377: is_semidrome (semidrome.c:35)

"分配大小为4的块....is_semidrome (semidrome.c: 35)">

所以这是你分配的大小为4字节的东西。

"无效写入大小为1…is_semidrome (semidrome.c: 39)">

这是你写到内存块的第5个字节的地方。

你不能把5个字节写入4个字节的空间。

最可能的修复方法是在第35行中所做的分配大小的基础上增加1。

最新更新