将char指针的地址传递给指向本地数组变量是否安全

将char指针的地址传递给指向本地数组变量是否安全,c,arrays,pointers,stack,C,Arrays,Pointers,Stack,实际上,在下面的程序中,我试图通过传递指针的addr来获取原因。根据栈的概念,栈帧中的局部变量在执行帧时被破坏。所以我的问题是,如何从main()访问函数中声明的缓冲区[100]。我只是糊涂了。无论如何,我得到了期望的输出 #include <stdio.h> #include <string.h> #define TCP_SYSLOG_MANUAL_BLOCK "TCP syslog manual blocking enabled" #define TCP_SYSLO

实际上,在下面的程序中,我试图通过传递指针的addr来获取原因。根据栈的概念,栈帧中的局部变量在执行帧时被破坏。所以我的问题是,如何从main()访问函数中声明的缓冲区[100]。我只是糊涂了。无论如何,我得到了期望的输出

#include <stdio.h>
#include <string.h>

#define TCP_SYSLOG_MANUAL_BLOCK "TCP syslog manual blocking enabled"
#define TCP_SYSLOG_MSQ_QFULL "TCP syslog message Queue full"
#define TCP_SYSLOG_HOST_DOWN "TCP Syslog server is DOWN"

void get_server_unreach_reason(char **reason)
{
        char buffer[100];
        printf("start addr of Buffer : %p\n", buffer);

        strncpy(buffer, TCP_SYSLOG_MANUAL_BLOCK, strlen(TCP_SYSLOG_MANUAL_BLOCK));
        printf("Buffer : %s\n", buffer);

        strcat(buffer, ", ");
        strncat(buffer, TCP_SYSLOG_MSQ_QFULL, strlen(TCP_SYSLOG_MSQ_QFULL));
        printf("Buffer : %s\n", buffer);

        strcat(buffer, ", ");
        strncat(buffer, TCP_SYSLOG_HOST_DOWN, strlen(TCP_SYSLOG_HOST_DOWN));
        printf("Buffer : %s\n", buffer);

        *reason = buffer;
}
int main()
{
        char *reason;
        get_server_unreach_reason(&reason);
        printf("reason pointing addr : %p\n", reason);
        printf("reason : %s\n", reason);
        return 0;
}
好了,现在我明白你的意思了。请您建议以下代码可以

void get_server_unreach_reason(char *buffer, int buflen)
{
        ....
        strncpy(buffer, TCP_SYSLOG_MANUAL_BLOCK, strlen(TCP_SYSLOG_MANUAL_BLOCK));
        printf("Buffer : %s\n", buffer);

}
int main()
{
        char reason[100];
        get_server_unreach_reason(reason, sizeof(reason));
        ....
}
如果可以的话,我还有一个问题。假设我们从不同的位置(调用者)调用get\u server\u unreach\u reason(),那么在所有调用者位置,我们都必须在传递到函数之前静态地分配缓冲区。

“只要堆栈帧仍然存在”,答案将是“是”

但是,我首先要说的是,你不应该这样做:没有什么(!)比“乱写堆栈的东西!”更糟糕的调试了。如果你想传递“指向某个东西的指针”,让“某个东西”总是(!)是你从堆中明确分配的东西

当然:“如果这真的是一个一次性函数调用,它将调用并立即返回,并且没有任何东西会试图记住您提供的指针值,”没问题。但是-我被烧死的次数太多了。

只要堆栈框架仍然存在,答案就是“是的”

但是,我首先要说的是,你不应该这样做:没有什么(!)比“乱写堆栈的东西!”更糟糕的调试了。如果你想传递“指向某个东西的指针”,让“某个东西”总是(!)是你从堆中明确分配的东西

当然:“如果这真的是一个一次性函数调用,它将调用并立即返回,并且没有任何东西会试图记住您提供的指针值,”没问题。但是-我被烧伤太多次了。

没有

函数返回的指针无效,因为它指向的内存已不存在

这似乎可行,但这纯粹是巧合。这种误用会在你最不经意的时候在你面前爆发,或者更典型地,在一个重要客户面前爆发

您需要声明局部变量
静态字符缓冲区[100]使其工作,但请注意,对该函数的任何调用都将返回相同的指针。

函数返回的指针无效,因为它指向的内存已不存在

这似乎可行,但这纯粹是巧合。这种误用会在你最不经意的时候在你面前爆发,或者更典型地,在一个重要客户面前爆发


您需要声明局部变量
静态字符缓冲区[100]
使其工作,但请注意,对函数的任何调用都将返回相同的指针。

在x86的大多数(所有?)调用约定中,堆栈帧在函数返回之前被销毁,即使在进行新函数调用之前内容可能是安全的。我敢打赌,目前所有主要平台都是如此。此外,访问这个指针是UB,编译器和stdlib有权对指向的位置做任何他们想做的事情,从毒害它以保护敏感信息到释放保存堆栈该部分的页面。最后,您可以将指向堆栈的指针安全地传递给被调用方。在x86的大多数(所有?)调用约定中,堆栈帧在函数返回之前被销毁,即使在进行新函数调用之前内容可能是安全的。我敢打赌,目前所有主要平台都是如此。此外,访问这个指针是UB,编译器和stdlib有权对指向的位置做任何他们想做的事情,从毒害它以保护敏感信息到释放保存堆栈该部分的页面。最后,您可以将指向堆栈的指针安全地传递给被调用方。我不会说它“能”爆炸,但它“会”在他们脸上爆炸。关于“它指向的记忆不再存在”:记忆仍然存在;从函数返回不会破坏RAM芯片。观察到的行为表明它仍然被映射。相反,当函数返回时,先前为
缓冲区提供的内存不再保留供该用途。而且,在C模型中,
buffer
的对象不再“存在”,但必须理解为谈论的是抽象模型,而不是物理对象的存在。Re“注意,对函数的任何调用都将返回相同的指针”:否,不同堆栈深度的调用将返回不同的地址。如果是静态的,则不会返回。我不会说它“可以”爆炸,而是说它“将”在它们的脸上爆炸。重新定义“它指向的内存不再存在”:内存仍然存在;从函数返回不会破坏RAM芯片。观察到的行为表明它仍然被映射。相反,当函数返回时,先前为
缓冲区提供的内存不再保留供该用途。而且,在C模型中,
buffer
的对象不再“存在”,但必须理解为谈论的是抽象模型,而不是物理对象的存在。Re“注意,对函数的任何调用都将返回相同的指针”:否,不同堆栈深度的调用将返回不同的地址。如果是静态的,则不会返回。
void get_server_unreach_reason(char *buffer, int buflen)
{
        ....
        strncpy(buffer, TCP_SYSLOG_MANUAL_BLOCK, strlen(TCP_SYSLOG_MANUAL_BLOCK));
        printf("Buffer : %s\n", buffer);

}
int main()
{
        char reason[100];
        get_server_unreach_reason(reason, sizeof(reason));
        ....
}