【发布时间】:2020-02-22 00:47:03
【问题描述】:
我正在尝试在 C 中实现 replace 函数。
我有 replace_str(char *str, char *sub, char *replacement) 函数将 char * 返回到修改后的字符串。
以下是函数:
#define ALLOC(size, type) (type *) calloc(size, sizeof(type))
#define REALLOC(ptr, new_size, type) (type *) realloc(ptr, new_size * sizeof(type))
/**
* Replaces all occurrences of given substring in string with given replacement.
* @param str A dynamically allocated string that will be modified.
* @param sub Old substring to be replaced.
* @param replacement New substring.
* @return The modified string.
*/
char *replace_str(char *str, char *sub, char *replacement) {
unsigned long len_sub = strlen(sub);
unsigned long len_rep = strlen(replacement);
if (len_sub != len_rep) {
unsigned long new_len = strlen(str) + (len_rep - len_sub) * count_substring(str, sub) + 1;
str = REALLOC(str, new_len, char);
}
char *ptr = strstr(str, sub);
while (ptr != NULL) {
char *str_tail = ptr + len_sub;
char *temp_tail = ALLOC(strlen(str_tail) + 1, char);
strcpy(temp_tail, str_tail);
strcpy(ptr, replacement);
strcat(str, temp_tail);
free(temp_tail);
ptr = strstr(ptr + len_rep, sub);
}
return str;
}
/* Counts number of non-overlapping times given substring mentioned in string. */
unsigned int count_substring(char *str, char *sub) {
unsigned int count = 0;
unsigned long sub_len = strlen(sub);
while (*str != '\0') {
if (strncmp(str++, sub, sub_len) != false)
continue;
str += sub_len - 1;
count++;
}
return count;
}
效果很好,但是当我有这样的事情时:
char *a = ALLOC(11, char);
strcpy(a, "\n\n\n\n\n\n\n\n\n\n");
while (CONTAINS(a, "\n\n")) {
a = replace_str(a, "\n\n", "\n");
}
free(a);
Valgrind 抱怨读取无效:
==896== Memcheck, a memory error detector
==896== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==896== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==896== Command: /mnt/d/archive/education/hu/assignments/fall2019/assignment1/cmake-build-debug/matrixman ../inputs/arrays ../inputs/IO/commands1.txt output1.txt
==896==
==896== Invalid read of size 1
==896== at 0x4C32D04: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==896== by 0x1091F2: replace_str (strutils.h:140)
==896== by 0x109496: main (main.c:33)
==896== Address 0x522d096 is 0 bytes after a block of size 6 alloc'd
==896== at 0x4C31D2F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==896== by 0x1091B7: replace_str (strutils.h:134)
==896== by 0x109496: main (main.c:33)
==896==
{
<insert_a_suppression_name_here>
Memcheck:Addr1
fun:strlen
fun:replace_str
fun:main
}
==896== Invalid read of size 1
==896== at 0x4C32E03: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==896== by 0x10921A: replace_str (strutils.h:141)
==896== by 0x109496: main (main.c:33)
==896== Address 0x522d096 is 0 bytes after a block of size 6 alloc'd
==896== at 0x4C31D2F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==896== by 0x1091B7: replace_str (strutils.h:134)
==896== by 0x109496: main (main.c:33)
==896==
{
<insert_a_suppression_name_here>
Memcheck:Addr1
fun:strcpy
fun:replace_str
fun:main
}
==896== Invalid read of size 1
==896== at 0x4C32CF2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==896== by 0x1091F2: replace_str (strutils.h:140)
==896== by 0x109496: main (main.c:33)
==896== Address 0x522d272 is 0 bytes after a block of size 2 alloc'd
==896== at 0x4C31D2F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==896== by 0x1091B7: replace_str (strutils.h:134)
==896== by 0x109496: main (main.c:33)
==896==
{
<insert_a_suppression_name_here>
Memcheck:Addr1
fun:strlen
fun:replace_str
fun:main
}
==896== Invalid read of size 1
==896== at 0x4FB7950: __strcpy_ssse3 (strcpy-ssse3.S:32)
==896== by 0x10921A: replace_str (strutils.h:141)
==896== by 0x109496: main (main.c:33)
==896== Address 0x522d272 is 0 bytes after a block of size 2 alloc'd
==896== at 0x4C31D2F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==896== by 0x1091B7: replace_str (strutils.h:134)
==896== by 0x109496: main (main.c:33)
==896==
{
<insert_a_suppression_name_here>
Memcheck:Addr1
fun:__strcpy_ssse3
fun:replace_str
fun:main
}
==896==
==896== HEAP SUMMARY:
==896== in use at exit: 0 bytes in 0 blocks
==896== total heap usage: 9 allocs, 9 frees, 34 bytes allocated
==896==
==896== All heap blocks were freed -- no leaks are possible
==896==
==896== For counts of detected and suppressed errors, rerun with: -v
==896== ERROR SUMMARY: 6 errors from 4 contexts (suppressed: 0 from 0)
当我在递归函数中使用replace_str 时也会发生这种情况。
我该如何解决这个问题?我没看到什么?
【问题讨论】:
-
您在处理之前将字符串重新分配到更小的尺寸...