我试图释放用户定义函数中分配的内存。我计划在嵌入式设备上运行代码,STM32F303k8具有64Kb闪存和16KB SRAM。我没有尝试过代码,但我担心它不会做它应该做的事情。由于未能释放分配的内存,它将耗尽内存
我试图在我的自定义程序中释放内存,称为split。但是,它甚至不编译并且总是在free()函数崩溃。
//This happens somewhere in the main function
// str_gprmc is a string thats trying to be split
// "$GPRMC,130133.00,A,5741.6029848,N,01158.3855831,E,11.522,170.0,270319"
for (int k = 0; k < ARRAY_SIZE(str_gprmc); k++)
{
char **arr = NULL;
// Now do the splitting please
split(str_gprmc[k], ',', &arr);
}´
// and the split function
int split(const char *ptr_original_string, char delimiter, char ***ptr_main_array)
{
// This variable holds the number of times we think we shall iterate through our array once its split
int count = 1;
// This variable holds the number of characters we have to iterate through for each split string
int split_string_len = 1;
// This variable helps us iterate through collections
int i = 0;
// Points to the first character of the whole string
char *ptrTemp_string_holder;
// Points to the first character of a split string from the main string
char *t;
ptrTemp_string_holder = ptr_original_string;
// First we count the number of times the delimiter is occurring in the string we want to split
// Iterate through the string until we reach either the Courage Return character CR : '\r', the Line Feed LF : '\n' or the NULL : '\0'
while (*ptrTemp_string_holder != '\0')
{
if (*ptrTemp_string_holder == delimiter)
count++;
ptrTemp_string_holder++;
}
// allocate size in memory for our array. Size of a character is 1 byte * count
*ptr_main_array = (char**)malloc(sizeof(char*) * count);
if (*ptr_main_array == NULL) {
exit(1);
}
ptrTemp_string_holder = ptr_original_string;
// Now start iterating through the whole unsplit string as long as we're not at the end
while (*ptrTemp_string_holder != '\0')
{
// If the pointer points to a delimiter, i.e a comma, that means we are starting to read a new string
if (*ptrTemp_string_holder == delimiter)
{
// Now allocate a memory size for a pointer to a pointer of the new string to be built
(*ptr_main_array)[i] = (char*)malloc(sizeof(char) * split_string_len);
// If its null, like some GPRMC or GPHDT results that come back empty, just exit and return back to main
if ((*ptr_main_array)[i] == NULL)
{
exit(1);
}
// Reset the token length and just move the hell on
split_string_len = 0;
i++;
}
ptrTemp_string_holder++;
split_string_len++;
}
// If we are not at a delimiter however, we just allocate a size based on our token length to a pointer of a pointer
// Or if you want, call it a pointer to an array
(*ptr_main_array)[i] = (char*)malloc(sizeof(char) * split_string_len);
// If for some unknown reason it was null, just stop the crap and return back to main...after all we got a shitty GPS device
if ((*ptr_main_array)[i] == NULL) exit(1);
i = 0;
ptrTemp_string_holder = ptr_original_string;
t = ((*ptr_main_array)[i]);
// Now that we got what we need, we rebuild back everything to formulate a pointer to a pointer of character strings
// I think then the rest is straight forward
while (*ptrTemp_string_holder != '\0')
{
if (*ptrTemp_string_holder != delimiter && *ptrTemp_string_holder != '\0')
{
*t = *ptrTemp_string_holder;
t++;
}
else
{
*t = '\0';
i++;
t = ((*ptr_main_array)[i]);
}
ptrTemp_string_holder++;
}
// Free the space that was allocated to this pointer
free(ptr_main_array);
// We return back the number of times we need to iterate to get the split components of the original string
return count;
}
您的代码中有两个无效的免费
一个在这里:
char *ptrTemp_string_holder; // Points to the first character of a split string from the main string char *t; free(ptrTemp_string_holder );
而ptrTemp_string_holder
尚未初始化
第二个就在结束之前:
// Free the space that was allocated to this pointer free(ptr_main_array);
因为你试图在调用函数中释放局部变量arr
必须删除这两个免费。
注意ptrTemp_string_holder
的定义必须是
const char *ptrTemp_string_holder;
因为它收到ptr_original_string
的值
由于未能释放分配的内存,它将耗尽内存
你需要释放*ptr_main_array
和记忆的数组,看起来很奇怪,在拆分其他拆分不返回可用的结果,必须在调用函数中完成,例如添加以下main:
int main()
{
char **arr = NULL;
int count = split("aze,qsd", ',', &arr);
if (arr != NULL) {
for (int i = 0; i != count; ++i)
free(arr[i]);
free(arr);
}
}
valgrind下的编译和执行:
pi@raspberrypi:/tmp $ gcc -pedantic -Wall -Wextra -g s.c
pi@raspberrypi:/tmp $ valgrind --leak-check=full ./a.out
==10755== Memcheck, a memory error detector
==10755== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10755== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==10755== Command: ./a.out
==10755==
==10755==
==10755== HEAP SUMMARY:
==10755== in use at exit: 0 bytes in 0 blocks
==10755== total heap usage: 3 allocs, 3 frees, 16 bytes allocated
==10755==
==10755== All heap blocks were freed -- no leaks are possible
==10755==
==10755== For counts of detected and suppressed errors, rerun with: -v
==10755== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
这对我来说完全没有意义:
// str_gprmc is a string thats trying to be split
// "$GPRMC,130133.00,A,5741.6029848,N,01158.3855831,E,11.522,170.0,270319"
for (int k = 0; k < ARRAY_SIZE(str_gprmc); k++)
{
char **arr = NULL;
// Now do the splitting please
split(str_gprmc[k], ',', &arr);
}´
// and the split function
int split(const char *ptr_original_string, char delimiter, char ***ptr_main_array)
如果我得到正确的话,str_gprmc
是char []
类型的变量,有一些大小,这里没有说明。您在数组中使用for(int k=....)
循环进行迭代。表达式str_gprmc[k]
从数组中提取k
-th字符,并将其作为第一个参数传递给split()
函数,该函数需要将char指针作为第一个参数。
这意味着char
类型数据的数字表示被解释为指针(const char *)
的数字表示。因此,您可以在初始120字节内存中的随机地址上有效地运行split()
,这取决于NMEA消息中字符的数值(ASCII代码) - 但您肯定不会处理消息本身。