[英]array of pointers pointing to spaces allocated in calling function and write in called function
我在func
有这段代码,我得到了指向指针数组的指针。 此函数的目的是将字符串写入两个为chars
分配的空间。 分配在主要。 我在这条线上收到了 segFault
memcpy(*c[1],"hi",sizeof("hi"));
这是完整的代码
void func(char (**c)[])
{
memcpy(*c[0],"hello",sizeof("hel"));
memcpy(*c[1],"hi",sizeof("hi"));
}
int main()
{
char (*arr)[2]=malloc(sizeof(char[2][10]));
func(&arr);
printf("%s\n",arr[0]);
printf("%s\n", arr[1]);
return 0;
}
我已经使用分配了指针数组
char (*arr)[2]=malloc(sizeof(char[2][10]));
现在传递两个分配的字符串空间的地址,我像这样调用
func(&arr);
传递指针数组的地址变量arr
的点,以便我可以看到main(...)
字符串空间的更改,在FUNC
所做的更改
但是这条线引起了麻烦
memcpy(*c[1],"hi",sizeof("hi"));
段错误
谁能告诉我我做错了什么这个答案也与指针数组有关。 https://stackoverflow.com/a/69551741/4808760
我期待的输出是
hell
hi
Valgrind 转储
valgrind --leak-check=full -s ./a.out
==7397== Memcheck, a memory error detector
==7397== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7397== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==7397== Command: ./a.out
==7397==
==7397== Invalid write of size 2
==7397== at 0x4849F23: memcpy@GLIBC_2.2.5 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7397== by 0x1091F2: func (test.c:8)
==7397== by 0x10922A: main (test.c:18)
==7397== Address 0x54698dcdde89a700 is not stack'd, malloc'd or (recently) free'd
==7397==
==7397==
==7397== Process terminating with default action of signal 11 (SIGSEGV)
==7397== General Protection Fault
==7397== at 0x4849F23: memcpy@GLIBC_2.2.5 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7397== by 0x1091F2: func (test.c:8)
==7397== by 0x10922A: main (test.c:18)
==7397==
==7397== HEAP SUMMARY:
==7397== in use at exit: 30 bytes in 1 blocks
==7397== total heap usage: 1 allocs, 0 frees, 30 bytes allocated
==7397==
==7397== LEAK SUMMARY:
==7397== definitely lost: 0 bytes in 0 blocks
==7397== indirectly lost: 0 bytes in 0 blocks
==7397== possibly lost: 0 bytes in 0 blocks
==7397== still reachable: 30 bytes in 1 blocks
==7397== suppressed: 0 bytes in 0 blocks
==7397== Reachable blocks (those to which a pointer was found) are not shown.
==7397== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==7397==
==7397== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==7397==
==7397== 1 errors in context 1 of 1:
==7397== Invalid write of size 2
==7397== at 0x4849F23: memcpy@GLIBC_2.2.5 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7397== by 0x1091F2: func (test.c:8)
==7397== by 0x10922A: main (test.c:18)
==7397== Address 0x54698dcdde89a700 is not stack'd, malloc'd or (recently) free'd
==7397==
==7397== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
一种方法是:
#include <stdio.h>
#include <stdlib.h>
void func(char **c)
{
c[0] = malloc(strlen("hel") + 1);
c[1] = malloc(strlen("hi") + 1);
strcpy(c[0], "hel");
strcpy(c[1], "hi");
}
int main()
{
char *arr[2];
func(arr);
printf("%s\n",arr[0]);
printf("%s\n", arr[1]);
return 0;
}
这里, arr
是一个由两个指向char
指针组成的数组。 当我们将数组传递给函数时,它会衰减为指向第一个元素的指针。 因此, func()
接受一个指向char
指针的指针。 c[0]
和c[1]
将保存malloc()
返回的地址到c
那些偏移量。 然后, strcpy()
只是将传递的字符串复制到分配的空间。 当这个函数返回时, main()
发现数据已经放在arr[0]
和arr[1]
。
或者,您也可以在func()
调用strdup()
func()
。 另外,不要忘记调用free()
。
在这份声明中
char (*arr)[2]=malloc(sizeof(char[2][10]));
arr
是一个指向2
字符的数组的指针。 然而,您正在为其分配2
个10
字符数组的内存。 它应该是
char (*arr)[10] = malloc(sizeof(char[2][10]));
^^^^
&arr
的类型是char (**)[10]
,所以func()
函数参数的类型应该是char (**)[10]
void func(char (**c)[10])
^^^^
在func()
函数中,您应该分别访问第一个和第二个数组,如(*c)[0]
和(*c)[1]
。
我期待的输出是
地狱
您将要复制的字符数作为sizeof("hel")
给memcpy()
sizeof("hel")
。 你想输出hell
或hel
? 我相信(或假设),您希望将字符串文字"hello"
前3
字符复制到(*c)[0]
。
请注意, sizeof("hel")
将给出输出4
因为它也包含空终止符。 因此, memcpy()
将从字符串文字"hello"
复制4
字符。 如果要从字符串"hello"
复制前3
字符,则应将计数传递为sizeof("hel") - 1
。
此外,您应该在使用memcpy()
复制字符后附加空终止符,因为memcpy()
不会自动附加终止空字符。 你可以这样做:
memcpy((*c)[0],"hello",sizeof("hel") - 1);
(*c)[0][sizeof("hel") - 1] = '\0'; // append null terminator character
最后,遵循良好的编程习惯,始终检查malloc()
返回并确保在完成后free()
动态分配的内存。
把这些放在一起,你可以这样做:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(char (**c)[10]) {
memcpy((*c)[0], "hello", sizeof("hel") - 1);
(*c)[0][sizeof("hel") - 1] = '\0';
memcpy((*c)[1], "hi", sizeof("hi") - 1);
(*c)[1][sizeof("hi") - 1] = '\0';
}
int main(void) {
char (*arr)[10] = malloc(sizeof(char[2][10]));
if (arr == NULL) {
fprintf (stderr, "Failed to allocate memory\n");
exit(EXIT_FAILURE);
}
func(&arr);
printf("%s\n", arr[0]);
printf("%s\n", arr[1]);
free(arr);
return 0;
}
输出:
# ./a.out
hel
hi
传递指针数组的地址变量 arr 的点,以便我可以看到
main(...)
字符串空间的变化
因为,你是分配内存以arr
的指针main()
之前调用函数func()
函数,你并不需要传递的地址arr
以反映更改到字符串空间main()
从返回后功能func()
功能。 只需将arr
传递给func()
函数。 当您传递arr
,这意味着您将指向已分配内存的指针传递给func()
函数,因此,将在func()
写入该内存的任何内容都将反映在main()
。 您还需要更改func()
参数的类型,使其与arr
类型相同,即char (*)[10]
并分别访问第一个和第二个数组,如c[0]
和c[1]
。 你可以做
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(char (*c)[10]) {
memcpy(c[0], "hello", sizeof("hel") - 1);
c[0][sizeof("hel") - 1] = '\0';
memcpy(c[1], "hi", sizeof("hi") - 1);
c[1][sizeof("hi") - 1] = '\0';
}
int main(void) {
char (*arr)[10] = malloc(sizeof(char[2][10]));
if (arr == NULL) {
fprintf (stderr, "Failed to allocate memory\n");
exit(EXIT_FAILURE);
}
func(arr);
printf("%s\n", arr[0]);
printf("%s\n", arr[1]);
free(arr);
return 0;
}
要解决您的代码的实际问题:
char (*arr)[2]
是错误的。 您希望它指向char [2][10]
的第一项。 这是一个包含 2 个项目的数组,其中每个项目都是一个包含 10 个字符的数组。 因此指针应该是char (*arr)[10]
。func(&arr);
没有意义,除非您打算更改指针本身(例如在函数内部执行 malloc 时),否则没有理由通过引用传递指针。char (**c)[]
是无稽之谈。 这是一个指向不完整数组类型的指针数组的指针。 但是您不能将不完整的数组类型作为参数传递给函数。 这应该是char str[2][10]
,它作为参数“衰减”为等效的char (*str)[10]
。\\0
。 请注意,malloc(与 calloc 不同)不会对分配的内存进行零初始化。free()
。 是的,操作系统会释放内存,但您仍然应该显式调用free()
,因为这会增加在设计阶段早期暴露堆损坏/指针/内存泄漏错误的机会。更正的代码:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void func(char str[2][10])
{
strcpy(str[0],"hello");
strcpy(str[1],"hi");
}
int main (void)
{
char (*arr)[10]=malloc(sizeof(char[2][10]));
func(arr);
printf("%s\n",arr[0]);
printf("%s\n", arr[1]);
free(arr);
return 0;
}
感谢我从 babon 那里得到的答案。
我也可以在 main 中分配空格,或者如果我需要在一行中创建空格,那么这就是char (*arr)[2]=malloc(sizeof(char[2][2]))
但我做到了没有得到答案如何在链接答案中的主函数或被调用函数中传递和分配数据。 刚刚告诉我如何分配它
void func(char **c)
{
memcpy(c[0],"hello",sizeof("hel"));
memcpy(c[1],"hi",sizeof("hi"));
// memcpy(*c[2],"hell",sizeof("hell"));
// c[0]="hello";
//c[1]="hi";
}
int main()
{
char *arr[2];
arr[0]=malloc(sizeof(char[2][10]));
arr[1]=malloc(sizeof(char[2][10]));
func(arr);
printf("%s\n",arr[0]);
printf("%s\n", arr[1]);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.