从Java切换到C,我有一些麻烦抓住内存管理
假设我有一个行为*check_malloc
,表现如下:
// Checks if malloc() succeeds.
void *check_malloc(size_t amount){
void *tpt;
/* Allocates a memory block in amount bytes. */
tpt = malloc( amount );
/* Checks if it was successful. */
if ( tpt == NULL ){
fprintf(stderr, "No memory of %lu bytes\n", amount);
exit(1);
}
return tpt;
}
我还可以使用以下变量:
FILE *f = fopen("abc.txt", "r"); // Pointer to a file with "mynameisbob" on the first line and
// "123456789" on the second line
char *pname; // Pointer to a string for storing the name
}
我的目标是使用*check_malloc
动态分配内存,以便String
指向的*pname
只是存储" mynamisbob"的正确大小,是文本文件第一行的唯一内容。
这是我的(失败)尝试:
int main(int argc, char *argv[]){
FILE *f = fopen("abc.txt", "r"); // A file with "mynameisbob" on the first line and
// "123456789" on the second line
char *pname; // Pointer to a string for storing the name
char currentline[150]; // Char array for storing current line of file
while(!feof(f)){
fgets(currentline,100,f);
pname = ¤tline;
}
但我知道这可能不是解决这个问题的方法,因为我需要使用我的check_malloc*
函数。
此外,在我的实际文本文件中有一个"<"第一行上的名称前面的符号。但我只想让*pname
指向一个字符串说" mynameisbob"没有"<"符号。现在这并不重要,它只是对我的强化,我知道我不能将指针设置为直接指向currentline
。
任何人都可以帮助我解决这个问题吗?非常感谢。
答案 0 :(得分:0)
在C中你需要复制字符,而不是“字符串”(它们只是指针)。查看strcpy()和strlen()。使用strlen()来确定fgets读取的实际行数,然后使用malloc()来精确分配(0加1)。然后使用strcpy()复制字符。
答案 1 :(得分:0)
您的代码中存在多个问题,请参阅此示例中的注释:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Checks if malloc() succeeds.
void *check_malloc (size_t amount) {
void *tpt;
/* Allocates a memory block in amount bytes. */
tpt = malloc( amount );
/* Checks if it was successful. */
if (tpt == NULL) {
fprintf (stderr, "No memory of %lu bytes\n", amount);
exit (EXIT_FAILURE);
}
return tpt;
}
// To avoid subtle errors I have defined buffer size here
#define BUFFER_SIZE 150
// I have used the (void) version of main () here, while not strictly neccessary, you where not using argc and argv anyway, so the can be left out in this case
int main (void) {
// It might be a good idea to make the filename a char[] as well, but I leave that as an exercise to the reader.
FILE *f = fopen("abc.txt", "r"); // A file with "mynameisbob" on the first line and
// "123456789" on the second line
// You have to check whether the file was *actually openend*
if (f == NULL) {
fprintf (stderr, "Could not open file abc.txt\n"); // '"...%s\n", filename);' might better.
exit (EXIT_FAILURE);
}
char *pname; // Pointer to a string for storing the name
char currentline[BUFFER_SIZE]; // Char array for storing current line of file
while(!feof (f)) {
char *res = fgets (currentline, BUFFER_SIZE, f);
// fgets returns NULL when EOF was encountered before the next '\n'
if (res) {
size_t read = strlen (res);
// The line might have been empty
if (read) {
// Better use "sizeof *varname", while char is always 1 byte it is a good practice
pname = check_malloc ((read + 1) * sizeof *pname); // + 1 because we have to provide an extra char für '\0'
strncpy (pname, currentline, read); // You have to use strcpy or strncpy to copy the contents of the string rather than just assigning the pointer
// What was allocated must be freed again
free (pname);
}
}
}
fclose(f); // Always close everything you open!
return EXIT_SUCCESS;
}
实际上,在这个简单的情况下你真的不必使用pname
,因为currentline
已经包含了这一行,但是既然你正在尝试了解内存管理,那么这应该让您大致了解事情是如何运作的。
在你的代码中你有这一行:
pname = ¤tline;
这里有两个问题:
正如我在代码中已经提到的那样,将当前行分配给pname只会复制指针而不是内容。
正确的分配是pname = currentline
(没有地址运算符&
),因为currentline
也是引擎盖下的指针(它的行为类似于char *currentline
即使它是静态分配的。)