C语言 如何修复似乎不适用的Valgrind条件跳转错误?

l2osamch  于 2022-12-03  发布在  其他
关注(0)|答案(1)|浏览(143)

我正在编写一个C程序,它将确定一个给定的字符串是否是半字符串(由两个或更多回文串组成),虽然我的解决方案确实有效,但我一直收到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] = '\0';
      // 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] = '\0';
        // 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错误。

7d7tgy0s

7d7tgy0s1#

看看你的代码,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。

相关问题