[英]How can heap objects use data from the stack?
I've declared the struct
foo like this:我已经像这样声明了struct
foo:
struct foo {
const char* name_lower;
const char* name_caps
//..
};
I dynamically create instances of foo
on the heap and want to save a value in the name_lower
and name_caps
member variable.我在堆上动态创建foo
实例,并希望在name_lower
和name_caps
成员变量中保存一个值。 This is done by the function bar
这是由功能bar
完成的
void bar(foo* entry, const char* str, int delimiter_pos) {
char l[2] = {str[caps_pos-1], '\0'}; // create new string
char c[2] = {str[caps_pos+1], '\0'};
entry->name_lower = &l[0]; // assign these strings the foo instance
entry->name_caps = &c[0];
}
I am worried, because I don't know if this code is going to crash.我很担心,因为我不知道这段代码会不会崩溃。 The temporarily created arrays l
and c
will be saved on the stack.临时创建的数组l
和c
将保存在堆栈中。 Once the function terminates the stack will be cleared up and c
and l
will probably disappear.一旦函数终止,堆栈将被清除并且c
和l
可能会消失。
Does this mean that the foo
instance will lose its names, ie its references?这是否意味着foo
实例将丢失其名称,即其引用? If so, how can I solve this problem?如果是这样,我该如何解决这个问题?
Continuing from the comment, the easiest way to allocate/copy and assign the start address for new blocks of memory for l
and c
is to use strdup
(from string.h
):继续注释,为l
和c
新内存块分配/复制和分配起始地址的最简单方法是使用strdup
(来自string.h
):
void bar(foo* entry, const char* str, int delimiter_pos) {
char l[2] = {str[caps_pos-1], '\0'}; // create new string
char c[2] = {str[caps_pos+1], '\0'};
entry->name_lower = strdup (l); // assign these strings the foo instance
entry->name_caps = strdup (c);
}
Don't forget to free
the memory allocated to entry->name_lower
and entry->name_caps
when no longer needed.不要忘记在不再需要时free
分配给entry->name_lower
和entry->name_caps
的内存。
You should instead use char *l = (char *)malloc(2 * sizeof(char));
你应该改用char *l = (char *)malloc(2 * sizeof(char));
and then initialize it;然后初始化它; similarly for char *c
.同样对于char *c
。 Then set entry->name_lower = l; entry->name_caps = c;
然后设置entry->name_lower = l; entry->name_caps = c;
entry->name_lower = l; entry->name_caps = c;
When allocating make sure you check whether the allocation succeeded, ie whether malloc
returned non-NULL address.分配时一定要检查分配是否成功,即malloc
是否返回了非NULL地址。
Make sure you free the memory after you don't need it anymore: free(entry->name_lower); free(entry->name_caps);
确保在不再需要内存后释放内存: free(entry->name_lower); free(entry->name_caps);
free(entry->name_lower); free(entry->name_caps);
. .
It will not lose anything.它不会失去任何东西。 The pointers in the struct
will retain their value, but the content will change and you will eventually get SIGSEGV. struct
的指针将保留其值,但内容会发生变化,您最终将获得 SIGSEGV。
For the char *
to persist, you need to allocate it on the heap too.为了让char *
持久化,您还需要在堆上分配它。
void bar(foo* entry, const char* str, int delimiter_pos) {
char * l = malloc(2);
char * c = malloc(2);
/* Check l and c for NULLs */
l[0] = str[caps_pos-1];
l[1] = '\0';
c[0] = str[caps_pos+1];
c[1] = '\0';
entry->name_lower = l;
entry->name_caps = c;
}
Remember that you should also free()
the struct members when you will no longer need it.请记住,当您不再需要结构成员时,您还应该free()
结构成员。
If you have a limit on the length of your strings, you can use char
arrays instead of pointers.如果您对字符串的长度有限制,则可以使用char
数组而不是指针。 In your example, all strings have a length of 1. Assuming your strings cannot be longer than that, you can use char[2]
instead of char*
:在您的示例中,所有字符串的长度均为 1。假设您的字符串不能超过该长度,您可以使用char[2]
而不是char*
:
struct foo {
char name_lower[2];
char name_caps[2];
//..
};
void bar(foo* entry, const char* str, int delimiter_pos) {
entry->name_lower[0] = str[caps_pos-1];
entry->name_lower[1] = '\0';
entry->name_caps[0] = str[caps_pos+1];
entry->name_caps[1] = '\0';
}
Historical note:历史记录:
Because this is so easy to use, people got accustomed to this, and forced artificial limits on string length, leading to buffer overflows.由于它非常易于使用,人们习惯了这一点,并强制人为地限制字符串长度,导致缓冲区溢出。 If your strings are not limited, use dynamic allocation instead of char
arrays.如果您的字符串不受限制,请使用动态分配而不是char
数组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.