strerrorname_np和strerrordesc_np导致linux gcc上的seg故障

643ylb08  于 2023-08-03  发布在  Linux
关注(0)|答案(1)|浏览(262)

我一直在阅读info libc,在2.3节“错误报告-错误消息”中提到了以下两个函数:
--功能:const char * strerrorname_np(int ERRNUM)

| MT-Safe | AS-Safe | AC-Safe | *Note POSIX Safety Concepts::.

This function returns the name describing the error ERRNUM or
‘NULL’ if there is no known constant with this value (e.g >"EINVAL"
for ‘EINVAL’).

This function is a GNU extension, declared in the header file
‘string.h’.

字符串
--功能:const char * strerrordesc_np(int ERRNUM)

| MT-Safe | AS-Safe | AC-Safe | *Note POSIX Safety Concepts::.

This function returns the message describing the error ERRNUM or
‘NULL’ if there is no known constant with this value (e.g >"Invalid
argument" for ‘EINVAL’).  Different than ‘strerror’ the returned
description is not translated.


但是这些函数在我的Linux(Ubuntu)机器上并不像预期的那样工作。它们可以编译,但会导致一个警告,说我试图在'char *'所属的类型中使用'int'。此外,当程序运行时,它导致seg故障。
下面是一些示例代码,我故意滥用fopen来生成errno,然后尝试使用上述函数:

#include <errno.h>  /* errno  */
#include <stdio.h>  /* printf */
#include <string.h> /* <-- functions should be here! */

void error_reporting_example(void)
{
    /* to generate an error, I'll pass fopen a bad flag */
    FILE * file = fopen("some_file", "bad_flags");
    if(file == NULL)
    {
        int errno_saved = errno;
        printf("ERROR: fopen failed with errno = %d\n\tError Name: %s\n\tError Description: %s\n", 
                errno_saved, 
                strerrorname_np(errno_saved),
                strerrordesc_np(errno_saved));
    }
}


结果输出为

$ ./test
ERROR: fopen failed with errno = 22
Segmentation fault (core dumped)


考虑到我的文档已经过时或者libc不兼容,我验证了string. h中函数prototyptes的存在

$ grep -rns /usr/include -e 'strerrordesc_np'
/usr/include/string.h:450:extern const char *strerrordesc_np (int __err) __THROW;
$ grep -rns /usr/include -e 'strerrorname_np'
/usr/include/string.h:452:extern const char *strerrorname_np (int __err) __THROW;


我运行带有-H标志的gcc来列出在编译有问题的文件时使用的头文件,以验证是否包含/usr/include/string. h

mkshixfv

mkshixfv1#

the man page中比在信息文档中更明显地说明了它,但是由于strerrordesc_np()strerrorname_np()是GNU扩展,因此在包含任何头文件之前需要定义_GNU_SOURCEfeature test macro,以便使这些函数可用。
如果你在问题中包含了编译时得到的完整警告,那么它应该包含那些函数的隐式声明。如果没有原型,编译器会假设它们返回int的,而返回一个指针最终会导致未定义的行为表现为segfault。
调整你的源代码,第一行是

#define _GNU_SOURCE

字符串
并且它应该如预期的那样工作。

相关问题