调用 free() 有时会导致程序崩溃
Calling free() sometimes causes program to crash
下面的代码要求用户输入 10 对艺术家和标题,最长可达 30 个字符。分配 space 并重新打印数据似乎一切正常。仅当我尝试在结束时释放内存并且仅当其中一个元素的长度为 4 个或更多字符时,才会出现此问题。我怀疑我没有正确分配内存,但我看不到它。
// Songs.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
// Experimenting with pointers, structures and dynamic allocation of memory
//
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <iostream>
#include <stdio.h>
struct songInfo
{
char* pArtist; // char pointer for Artist data
char* pTitle; // char pointer for Title data
};
// function prototype declarations
void getSongInfo(struct songInfo *songData, char *Artist, char *Title);
void printSongInfo(songInfo *songData);
int main()
{
struct songInfo songData[10]; // setup array of 10 elements of the structure SongInfo
char sArtist[31];
char sTitle[31];
// prompt user for the artist and title 10 times once for each array element
for (int i = 0; i < 10; i++) {
printf("Artist %i: ", i + 1);
fgets(sArtist, 31, stdin);
strtok(sArtist, "\n"); // trim out return character
printf("Title %i: ", i + 1);
fgets(sTitle, 31, stdin);
strtok(sTitle, "\n"); // trim out return character
getSongInfo(&songData[i], sArtist, sTitle); // allocates the memory and stores the data into the pointer location
}
printSongInfo(songData); // printout the song data stored in the array
// free up the allocated memory space
for (int i = 0; i < 10; ++i) {
free(songData[i].pArtist);
free(songData[i].pTitle);
}
return 0;
}
void getSongInfo(struct songInfo *songData, char *Artist, char *Title) {
songData->pArtist = (char*)malloc(sizeof(Artist) + 1); // Allocate enough memory to hold the string and the null terminator
songData->pTitle = (char*)malloc(sizeof(Title) + 1);
strcpy(songData->pArtist, Artist); // Copy the data into the allocated memory location
strcpy(songData->pTitle, Title);
}
void printSongInfo(songInfo *songData) {
printf("\n%-35s %-35s\n", "Artist", "Title");
printf("%-35s %-35s\n", "-----------------------------------", "-----------------------------------");
for (int i = 0; i < 10; i++) { // iterate through the array of elements
printf("%-35s %-35s\n", songData[i].pArtist, songData[i].pTitle);
}
}
无效的不是free()
调用,而是malloc
。
如果您打印出 sizeof(Artist) + 1
,您可能会得到 5
或 9
(取决于您的计算机体系结构)。 Title
也是如此。你在你的机器上检查指针的大小,它是常量,而不是你收到的数组的大小。
Undefined Behvaiour 意味着您的代码可以做任何事情,包括“暂时工作,但稍后会在正确的地方中断”。您通过调用 strcpy
来调用 UB,它会尝试将数据复制到太短而无法包含整个字符串的缓冲区中。
您必须将数组的大小传递给函数或使用函数内部的 strlen
计算它(并祈祷该字符串实际上以 null 结尾)。
void getSongInfo(struct songInfo *songData, char *Artist, char *Title) {
songData->pArtist = (char*)malloc(strlen(Artist) + 1); // Allocate enough memory to hold the string and the null terminator
songData->pTitle = (char*)malloc(strlen(Title) + 1);
strcpy(songData->pArtist, Artist); // Copy the data into the allocated memory location
strcpy(songData->pTitle, Title);
}
使用std::char_traits::length or strlen。 sizeof(Artist)
给出的不是数组的长度,而是 char *
指针占用的字节数。
songData->pArtist =
(char*)malloc(std::char_traits<char>::length(Artist) +
1); // Allocate enough memory to hold the string and the null terminator
songData->pTitle =
(char*)malloc(std::char_traits<char>::length(Title) +
1); // Allocate enough memory to hold the string and the null terminator
附带说明:使用 std::string
和 std::unique_ptr
和 std::shared_ptr
等智能指针可以为您省去很多处理内存问题的麻烦。总体而言,使用现代 c++
将帮助您更高效地编写更安全的代码。
下面的代码要求用户输入 10 对艺术家和标题,最长可达 30 个字符。分配 space 并重新打印数据似乎一切正常。仅当我尝试在结束时释放内存并且仅当其中一个元素的长度为 4 个或更多字符时,才会出现此问题。我怀疑我没有正确分配内存,但我看不到它。
// Songs.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
// Experimenting with pointers, structures and dynamic allocation of memory
//
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <iostream>
#include <stdio.h>
struct songInfo
{
char* pArtist; // char pointer for Artist data
char* pTitle; // char pointer for Title data
};
// function prototype declarations
void getSongInfo(struct songInfo *songData, char *Artist, char *Title);
void printSongInfo(songInfo *songData);
int main()
{
struct songInfo songData[10]; // setup array of 10 elements of the structure SongInfo
char sArtist[31];
char sTitle[31];
// prompt user for the artist and title 10 times once for each array element
for (int i = 0; i < 10; i++) {
printf("Artist %i: ", i + 1);
fgets(sArtist, 31, stdin);
strtok(sArtist, "\n"); // trim out return character
printf("Title %i: ", i + 1);
fgets(sTitle, 31, stdin);
strtok(sTitle, "\n"); // trim out return character
getSongInfo(&songData[i], sArtist, sTitle); // allocates the memory and stores the data into the pointer location
}
printSongInfo(songData); // printout the song data stored in the array
// free up the allocated memory space
for (int i = 0; i < 10; ++i) {
free(songData[i].pArtist);
free(songData[i].pTitle);
}
return 0;
}
void getSongInfo(struct songInfo *songData, char *Artist, char *Title) {
songData->pArtist = (char*)malloc(sizeof(Artist) + 1); // Allocate enough memory to hold the string and the null terminator
songData->pTitle = (char*)malloc(sizeof(Title) + 1);
strcpy(songData->pArtist, Artist); // Copy the data into the allocated memory location
strcpy(songData->pTitle, Title);
}
void printSongInfo(songInfo *songData) {
printf("\n%-35s %-35s\n", "Artist", "Title");
printf("%-35s %-35s\n", "-----------------------------------", "-----------------------------------");
for (int i = 0; i < 10; i++) { // iterate through the array of elements
printf("%-35s %-35s\n", songData[i].pArtist, songData[i].pTitle);
}
}
无效的不是free()
调用,而是malloc
。
如果您打印出 sizeof(Artist) + 1
,您可能会得到 5
或 9
(取决于您的计算机体系结构)。 Title
也是如此。你在你的机器上检查指针的大小,它是常量,而不是你收到的数组的大小。
Undefined Behvaiour 意味着您的代码可以做任何事情,包括“暂时工作,但稍后会在正确的地方中断”。您通过调用 strcpy
来调用 UB,它会尝试将数据复制到太短而无法包含整个字符串的缓冲区中。
您必须将数组的大小传递给函数或使用函数内部的 strlen
计算它(并祈祷该字符串实际上以 null 结尾)。
void getSongInfo(struct songInfo *songData, char *Artist, char *Title) {
songData->pArtist = (char*)malloc(strlen(Artist) + 1); // Allocate enough memory to hold the string and the null terminator
songData->pTitle = (char*)malloc(strlen(Title) + 1);
strcpy(songData->pArtist, Artist); // Copy the data into the allocated memory location
strcpy(songData->pTitle, Title);
}
使用std::char_traits::length or strlen。 sizeof(Artist)
给出的不是数组的长度,而是 char *
指针占用的字节数。
songData->pArtist =
(char*)malloc(std::char_traits<char>::length(Artist) +
1); // Allocate enough memory to hold the string and the null terminator
songData->pTitle =
(char*)malloc(std::char_traits<char>::length(Title) +
1); // Allocate enough memory to hold the string and the null terminator
附带说明:使用 std::string
和 std::unique_ptr
和 std::shared_ptr
等智能指针可以为您省去很多处理内存问题的麻烦。总体而言,使用现代 c++
将帮助您更高效地编写更安全的代码。