C语言malloc/free函数使用崩溃问题及字符串处理作业实现求助
Hey there! Let's break down why your free() is crashing and fix up your code to meet all the assignment requirements.
First: Why free() is causing a crash
The core issue is that you're trying to free memory that's not allocated on the heap. Look at this line:
char outPut[] = "";
This creates an array on the stack, not the heap. Later, you assign Ptr_outPut_address = &outPut; and call free(Ptr_outPut_address)—but free() only works with memory allocated via malloc/calloc/realloc. Freeing stack memory is undefined behavior, which directly causes your program to crash.
Other Critical Issues in Your Code
Before fixing the crash, let's list other problems that were causing undefined behavior or failing assignment requirements:
char inPut[] = "";creates a stack array of size 1 (only holds'\0'). Usingscanf("%s", inPut)will overflow this buffer, corrupting stack data.Ptr_inPut_addressis allocated but never used—this is unnecessary and clutters your code.- Your
realloccalls are wrong: the second parameter is the total new size, not the increment. You also mixed stack arrayoutPutwith heap pointerPtr_outPut_address, which means you were writing to stack memory while trying to manage heap memory—total chaos. - You didn't properly calculate the required output size upfront, which violates the "exact size" requirement.
Fixed Code That Meets All Requirements
Here's a revised version of your code with all issues addressed:
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> // Helper function to calculate exact required output length int calculate_output_length(const char* input) { int len = 0; while (*input != '\0') { if ((*input >= 'a' && *input <= 'z') || (*input >= 'A' && *input <= 'Z')) { len++; } else if (*input >= '0' && *input <= '9') { // Add count of digits from '9' down to (but not including) the input digit len += ('9' - *input); } input++; } return len; } int main() { system("cls"); int all_Ex_in_loop = 0; printf("Run menu once or cyclically?\n(Once - enter 0, cyclically - enter other number) "); if (scanf_s("%d", &all_Ex_in_loop) != 1) { fprintf(stderr, "Invalid input!\n"); return 1; } do { int select = 0; printf("Ex1--->1\n"); printf("Ex2--->2\n"); printf("Ex3--->3\n"); printf("EXIT--->0\n"); do { printf("please select 0-3 : "); if (scanf_s("%d", &select) != 1) { // Clear invalid input from buffer while (getchar() != '\n'); select = -1; // Force re-input } } while (select < 0 || select > 3); switch (select) { case 1: { // Safe input buffer (adjust size if needed for longer strings) char inPut[1024]; printf("Please enter a string :\n"); scanf_s("%s", inPut, (unsigned)_countof(inPut)); // Calculate exact memory needed for output int output_len = calculate_output_length(inPut); // Allocate exactly the right size (+1 for null terminator) char* outPut = (char*)malloc(output_len + 1); if (!outPut) { fprintf(stderr, "Memory allocation failed!\n"); break; } int idx = 0; const char* p = inPut; while (*p != '\0') { if (*p >= 'a' && *p <= 'z') { // Lowercase to uppercase outPut[idx++] = *p - 32; } else if (*p >= 'A' && *p <= 'Z') { // Uppercase to lowercase outPut[idx++] = *p + 32; } else if (*p >= '0' && *p <= '9') { // Generate descending digit sequence char current = '9'; while (current > *p) { outPut[idx++] = current; current--; } } // Skip all other characters p++; } // Add null terminator to make it a valid string outPut[idx] = '\0'; printf("Result: %s\n", outPut); // Free the heap-allocated memory (this is now safe!) free(outPut); outPut = NULL; // Avoid dangling pointer } break; case 2: printf("Ex2 is not implemented yet.\n"); break; case 3: printf("Ex3 is not implemented yet.\n"); break; case 0: printf("Exiting program...\n"); break; } } while (all_Ex_in_loop && select != 0); system("pause"); return 0; }
Key Fixes & Improvements
- Safe
free(): NowoutPutis allocated viamalloc()on the heap, sofree(outPut)is completely valid and won't crash. - Exact Memory Allocation: We first calculate the exact length needed for the output string, then allocate exactly that size (plus 1 for the null terminator)—this meets your assignment's requirement perfectly.
- Input Safety: Uses a fixed-size buffer with
scanf_sto prevent overflow. For very long inputs, you could dynamically allocate the input buffer too, but this works for most cases. - Cleaner Logic: Removed unused variables, simplified the character transformation loops, and fixed the menu/loop logic to work correctly.
- No Modification to Input: We only read from the input string, never modify it—complies with the assignment's rule.
Test this with your example input A$q6#G4—it will output aQ987g98765 as expected!
内容的提问来源于stack exchange,提问作者Cc4Dayz

