C语言自定义replace函数的动态内存管理问题排查
Let's break down the issues in your code that are causing the garbled output and runtime anomalies—most of them tie back to dynamic memory management and string termination, which are easy pitfalls in C:
1. Uninitialized new_text Breaks strcat
You start with char *new_text = malloc(new_text_size); where new_text_size is 0. While malloc(0) is implementation-defined (it might return NULL or a dummy pointer), the bigger problem is that new_text isn't initialized as an empty, null-terminated string. When you first call strcat(new_text, with), strcat looks for a \0 to start appending, and since your buffer is uninitialized, it'll read random memory until it finds one—this is exactly what's causing the weird <0� garbage at the start of your output.
Fix: Initialize new_text as an empty string from the get-go:
char *new_text = malloc(1); // Allocate space for the null terminator new_text[0] = '\0'; int new_text_size = 0; // Keep track of the actual character count (excluding null terminator)
2. Missing Null Terminator in new_text
Your loop builds new_text character by character or appends replacement strings, but you never add a final \0 to terminate the string. When you later call strcpy(*text, new_text), strcpy will keep reading past the end of your buffer until it hits a random null byte, leading to unexpected behavior.
Fix: After the loop finishes, resize new_text to make space for the terminator and add it:
// After the do-while loop new_text = realloc(new_text, new_text_size + 1); new_text[new_text_size] = '\0';
3. Insufficient Memory for the Final *text
When you assign *text = malloc(new_text_size);, you're not accounting for the null terminator. This means strcpy will write the terminator outside the allocated buffer, causing undefined behavior (like corrupting other memory).
Fix: Allocate an extra byte for the null terminator:
*text = malloc(new_text_size + 1); strcpy(*text, new_text);
4. Memory Leak from new_text
You never free the new_text buffer after copying its contents to *text. This will leave allocated memory hanging around, which is a bad practice in long-running programs.
Fix: Add free(new_text); right after copying to *text.
5. Minor Loop Adjustment (Avoiding Off-by-One)
Your do-while loop works mostly fine, but let's double-check: when you process the last character of the original string, p increments to \0, and the loop exits. That's correct, but to keep things safe, I added a null terminator every time we append a single character to new_text—this ensures the buffer is always valid for any intermediate operations.
Corrected Full Code
Here's the fixed version with all these changes applied:
#include <stdio.h> #include <string.h> #include <stdlib.h> void replace_content(char *rep, char *with, char **text) { int len_rep = strlen(rep); int len_with = strlen(with); char *p = *text; int new_text_size = 0; // Initialize new_text as an empty null-terminated string char *new_text = malloc(1); new_text[0] = '\0'; do { if (!strncmp(p, rep, len_rep)) { new_text_size += len_with; new_text = realloc(new_text, new_text_size + 1); // +1 for null terminator strcat(new_text, with); p += len_rep; } else { new_text_size++; new_text = realloc(new_text, new_text_size + 1); // +1 for null terminator new_text[new_text_size - 1] = *p; new_text[new_text_size] = '\0'; // Ensure buffer stays terminated p++; } } while (*p != '\0'); // Allocate proper space for the final text (including null terminator) *text = malloc(new_text_size + 1); strcpy(*text, new_text); // Clean up the temporary buffer free(new_text); } int main() { printf("Testing a replace function:\n"); char *text = "<serviceName>\n" " <label1>a</label1>\n" " <label2>b</label2>\n" " <label3>c</label3>\n" "</serviceName>\n"; printf("Before replace:\n%s", text); replace_content("serviceName>", "serviceNameResponse>", &text); printf("After replace:\n%s", text); // Don't forget to free the final text too! free(text); return 0; }
Additional Note
I also added free(text); in main() since you're replacing the original pointer with a dynamically allocated one—this prevents another memory leak.
When you run this corrected code, you'll get the expected output without any garbage characters or anomalies.
内容的提问来源于stack exchange,提问作者ArthurTheLearner

