所以,我正在做这个练习:
写一个C函数void occurrence(char * s,char c,char *** occp, int * n)给定一个字符串s和一个char c,计算其数量 在字符串s中出现char c,在n中返回该数字,并在中返回新的char 数组的地址,其中包含每个c的地址 发生在s
主要样本:
#include <stdio.h>
int main(){
int i, n;
char** occ;
occorrenze("engineering", 'n', &occ, &n);
for (i=0; i<n; ++i) printf("%s\n", occ[i]); // prints ngineering neering ng
free(occ);
}
最初我用这种方式写了这个函数:
void occurrences(char* s1, char c, char*** s, int* n){
*n=0;
char* arr[2];
int length=strlen(s1);
int i;
for(i=0; i<length; i++){
if(s1[i]==c)(*n)++;
}
*s=(malloc((*n)*sizeof(char**)));
int a=0;
for(i=0; i<length; i++){
if(s1[i]==c){
(*s)[a]= &s1[i];
a++;
}
}
}
工作得很好,但我想尝试重新编写一次迭代字符串。我想过使用realloc(),这是我以前从未使用过的函数,最终我想出了这个:
void occurrences(char* s1, char c, char*** s, int* n){
*n=0;
*s=malloc(0);
char* arr[2];
int length=strlen(s1);
int i,a=0;
for(i=0; i<length; i++){
if(s1[i]==c){
(*n)++;
*s=realloc(*s,(*n)*sizeof(char**));
(*s)[a]= &s1[i];
a++;
}
}
}
这个似乎运作良好,但后来我运行Valgrind:
==4893== HEAP SUMMARY:
==4893== in use at exit: 0 bytes in 0 blocks
==4893== total heap usage: 4 allocs, 4 frees, 48 bytes allocated
==4893==
==4893== All heap blocks were freed -- no leaks are possible
==4893==
==4893== For counts of detected and suppressed errors, rerun with: -v
==4893== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
分配了48个字节?它应该是24个字节,对吧? 总堆大小为8 * n!而不是8 * n ......我想我错过了一些XD
编辑:复制了正确的函数lol
答案 0 :(得分:4)
在整个应用程序的执行过程中,valgrind不会测量总分配的内存吗?
0 + 8 + 16 + 24 = 48。
答案 1 :(得分:0)
HEAP USAGE:
如果你malloc(1)
,系统会为你分配一块能够容纳一个字节的内存。你可能没有意识到,系统通常永远不会分配一个字节。实际上,分配的内存块很可能要大得多;也许至少8,16或32字节。因此,malloc()
ed空格不等于heap space
- 使用。
由于上述“最小”系统内存分配,函数realloc()
可能返回与给定的相同的地址;如果该地址的系统分配足够大,以适应(在您的情况下)更大的大小。一旦系统分配变得太小,realloc()
将向更大的系统内存块返回一个新地址(并且很可能比realloc请求的更大)。
一些评论:
void occurrences(char* s1, char c, char*** s, int* n){
*n=0;
*s=NULL;
更改了以上内容。无需malloc(0);
。 s
(NULL
)的值将传递到realloc()
,然后就像malloc()
一样,
char* arr[2];
int length=strlen(s1);
int i,a=0;
for(i=0; i<length; i++){
if(s1[i]==c){
(*n)++;
*s=realloc(*s,(*n) * sizeof(char**)); // !DANGER!
请考虑以下替代方案,而不是上述内容:
if(s1[i]==c){
char *tmp;
(*n)++;
tmp=realloc(*s,(*n) * sizeof(char**)); // Much better.
if(NULL == tmp)
{
/* Handle realloc() failure. */
...
}
else
*s = tmp;
...
如果您不按上面所示进行操作,如果realloc()
失败,则先前分配的内存(由s
指向)将丢失;由NULL
替换。
(*s)[a]= &s1[i];
a++;
}
}
}
答案 2 :(得分:0)
如果您不使用 *n 和 *occp 作为变量,而是使用局部变量并将它们存储在函数的最后,您可以省去大麻烦。使事情更清晰,并减少出现错误的机会。