gcc 4.9.2 bug in -Werror=sizeof-pointer-memaccess?

GCC 在使用 memset 时出现 `-Wsizeof-pointer-memaccess` 警告,原因是将 sizeof 运算应用于指针而非数组。这可能导致不正确的内存填充。解决方法是确保传递给 memset 的长度参数是目标缓冲区的实际大小,而不是指针本身的大小。对于动态分配的内存,需要使用实际分配的长度,而对于字符串,可以使用 strlen 函数来确定长度。

You fell straight into the trap.

In C, C++, Objective-C, Objective-C++, a parameter with a declaration that looks like "array of T" actually has type T*.

Your parameter charArray has a declaration that looks like "array of 100 chars", but the declaration is in fact "pointer to char".

Therefore, your third parameter to strncpy has a value of (most likely) 4 or 8, and not the 100 that you seem to expecct.

BTW. strncpy is highly dangerous the way you use it.

link: https://stackoverflow.com/questions/29186056/gcc-4-9-2-bug-in-werror-sizeof-pointer-memaccess

下面的代码中警告是什么原因,怎么解决

memset(m_pBuffer,0,sizeof(m_pBuffer));

warning: argument to 'sizeof' in 'void* memset(void*, int, size_t)' call is the same expression as the destination; did you mean to provide an explicit length? [-Wsizeof-pointer-memaccess]
memset(m_pBuffer,0,sizeof(m_pBuffer));

首先,m_pBuffer应该是个成员指针变量,不是数组名吧。sizeof 运算符对“指针变量”运算的结果是指针变量的字节大小(32位4字节,64位8字节),可不是其指向的数据的大小哦。
对数组名运算是为数组分配的空间的字节大小。
其次,这个警告:**-Wsizeof-pointer-memaccess**

Warn for suspicious length parameters to certain string and memory built-in functions if the argument uses sizeof.
This warning warns e.g. about memset (ptr, 0, sizeof (ptr)); if ptr is not an array, but a pointer, and suggests a possible fix, or about memcpy (&foo, ptr, sizeof (&foo));. This warning is enabled by -Wall.
gcc编译器检测到可疑的使用sizeof对指针做了运算而不是数组,所以给了个温馨提示哦。

怎么解决:
对指针指向的数据做sizeof,如果是new分配的还要乘上数量了。

memset的最后一个参数是你m_pBuffer指向缓冲区的长度,而不是m_pBuffer指针的长度。sizeof(m_pBuffer)求出来一般是4,也就是指针的长度。

m_pBuffer是指针,sizeof(指针) == 4;sizeof(m_pBuffer) 改成 strlen(m_pBuffer);

m_pBuffer是数组还是指针,如果是指针,你后面的sizeof得到的是指针大小4,而不是整个存储空间的长度。

用strlen试一下,如果是char类型的,wchar就用_tcslen

link: https://stackoverflow.com/questions/1461432/what-is-array-decaying

https://stackoverflow.com/questions/19202368/snprintf-error-argument-to-sizeof-is-the-same-as-destination

<think> 我们正在解释一组GCC编译选项,这些选项在开启时会将特定的警告视为错误(因为使用了-Werror=的形式)。每个选项对应一种特定的代码问题,编译器会因此产生错误而非警告,从而阻止编译过程。以下是对每个选项的详细解释及典型例子。 1. **-Werror=strict-prototypes** - **含义**:当函数声明或定义没有指定参数类型(即使用空参数列表)而非使用`void`表示无参数时,会触发该错误。在C语言中,空参数列表表示函数参数数量和类型未知(不进行参数检查),而使用`void`明确表示无参数。 - **典型例子**: ```c // 错误示例:函数声明不是原型(缺少参数类型说明) int foo(); // 应当改为 int foo(void); // 对应错误信息如引用[1]所示:error: function declaration isn’t a prototype ``` 2. **-Werror=implicit-function-declaration** - **含义**:当编译器遇到未事先声明的函数调用时,会隐式声明该函数(返回类型为`int`)。这通常是因为忘记包含头文件或函数声明导致的。该选项将此类情况视为错误。 - **典型例子**: ```c // 错误示例:未声明函数即调用 int main() { printf("Hello"); // 未包含<stdio.h>,且未声明printf return 0; } ``` - 错误信息:`error: implicit declaration of function &#39;printf&#39;` 3. **-Werror=implicit-int** - **含义**:当未明确指定变量或函数的返回类型时,编译器会默认类型为`int`。该选项将此类隐式使用`int`的情况视为错误。 - **典型例子**: ```c // 错误示例:函数返回类型和变量类型未显式声明 foo() { return 0; } // 应改为 int foo() {...} static x; // 应改为 static int x; ``` - 错误信息:`error: type defaults to &#39;int&#39; in declaration of &#39;foo&#39;` 4. **-Werror=return-type** - **含义**:当函数非`void`返回类型缺少返回值,或`void`函数尝试返回值时,会触发此错误。同时包括控制流可能到达函数结尾却没有返回语句的情况。 - **典型例子**: ```c // 错误示例1:非void函数缺少返回值 int func(int a) { if (a > 0) return 1; // 若a<=0,无返回值 } // 错误示例2:void函数返回值 void test() { return 5; } ``` - 错误信息:`error: control reaches end of non-void function` 5. **-Werror=date-time** - **含义**:当代码中使用`__DATE__`, `__TIME__`, `__TIMESTAMP__`宏时,该选项会将其视为错误。这些宏会嵌入编译时间信息,导致每次编译生成的二进制文件不同,不利于可重现构建(reproducible builds)。 - **典型例子**: ```c // 错误示例:使用时间宏 const char* build_time = __DATE__; ``` - 错误信息:`error: macro "__DATE__" might prevent reproducible builds` 6. **-Werror=incompatible-pointer-types** - **含义**:当赋值或传递指针时,目标指针类型与源指针类型不兼容(如`int*`赋给`char**`),且未进行显式强制转换时,会触发此错误。 - **典型例子**: ```c // 错误示例:指针类型不兼容 int x = 10; int* p = &x; char** pp = &p; // 错误:int** 与 char** 不兼容 ``` - 错误信息:`error: assignment to &#39;char **&#39; from incompatible pointer type &#39;int **&#39;` 7. **-Werror=designated-init** - **含义**:当使用C99指定的初始化器(designated initializers)但顺序错误或重复初始化同一成员时,会触发此错误。注意:GCC默认只对重复初始化报错,顺序问题属于`-pedantic`警告范畴;但若开启`-Werror=designated-init`,则指定初始化器的任何问题都会被视为错误。 - **典型例子**: ```c // 错误示例:重复初始化同一成员 struct S { int a; int b; }; struct S s = { .a = 1, .a = 2 }; // 重复初始化.a // 顺序问题示例(通常为警告,但若设为错误则同样报错) int arr[3] = { [1]=1, [0]=2 }; // C99允许乱序,但若开启-pedantic会警告(若-Werror则变错误) ``` - 错误信息:`error: duplicate initialization of field &#39;a&#39;` ### 使用建议 - **启用方式**:在编译命令中添加`-Werror=<警告名>`,如`gcc -Werror=strict-prototypes test.c`。 - **严格模式**:常用组合选项`-Wall -Wextra -Wpedantic -Werror`可将大多数警告升级为错误,提升代码质量。 - **禁用方法**:若需临时禁用某错误,可使用`-Wno-error=<警告名>`(如`-Wno-error=strict-prototypes`)。 §§相关问题§§ 1. 如何一次性启用所有警告并将警告视为错误? 2. 为什么`-Werror=designated-init`对初始化顺序的检查需要配合`-pedantic`? 3. 如何避免`-Werror=date-time`导致的编译失败? </think> ### GCC 编译选项详解及典型示例 以下是对指定 `-Werror=xxx` 选项的解释,这些选项会将特定警告升级为错误(编译失败),帮助开发者编写更严谨的代码: --- #### 1. **-Werror=strict-prototypes** [^1] **含义**:要求函数声明必须包含完整的参数类型(原型声明),禁止空参数列表。 **问题本质**:避免未指定参数的函数声明(如 `int func()`)导致类型检查缺失。 **典型例子**: ```c // 错误写法:缺少参数类型声明 int test(); // 触发错误 // 正确写法:明确参数类型 int test(void); // 显式声明无参数 int test(int a); // 显式声明参数类型 ``` --- #### 2. **-Werror=implicit-function-declaration** **含义**:禁止隐式函数声明(未声明即调用)。 **问题本质**:防止因缺失头文件包含导致函数签名错误。 **典型例子**: ```c int main() { printf("Hello"); // 错误:未包含<stdio.h>,隐式声明printf return 0; } // 修复:添加 #include <stdio.h> ``` --- #### 3. **-Werror=implicit-int** **含义**:禁止隐式使用 `int` 类型(未声明类型的变量/函数)。 **问题本质**:避免因类型缺失导致意外行为。 **典型例子**: ```c x = 10; // 错误:变量x未声明类型(隐式int) static y; // 错误:未声明类型 // 正确写法: int x = 10; static int y; ``` --- #### 4. **-Werror=return-type** **含义**:函数必须显式返回与声明一致的类型。 **问题本质**:防止非 `void` 函数遗漏返回值或 `void` 函数返回值。 **典型例子**: ```c int func() { // 错误:缺少return语句 } void test() { return 5; // 错误:void函数不应返回值 } ``` --- #### 5. **-Werror=date-time** **含义**:禁止使用 `__DATE__` 和 `__TIME__` 宏。 **问题本质**:确保编译结果可复现(避免时间戳导致二进制差异)。 **典型例子**: ```c printf("Build: %s %s", __DATE__, __TIME__); // 触发错误 // 替代方案:使用版本号或外部配置 ``` --- #### 6. **-Werror=incompatible-pointer-types** **含义**:禁止不兼容的指针类型转换。 **问题本质**:防止未经验证的指针转换引发内存错误。 **典型例子**: ```c int num = 10; int* p = &num; char** pp = &p; // 错误:int** 与 char** 不兼容 // 正确转换:显式类型转换并验证 char** pp = (char**)&p; // 需确保内存布局兼容 ``` --- #### 7. **-Werror=designated-init** **含义**:检查结构体指定初始化器的正确性。 **问题本质**:防止初始化顺序错误或字段重复。 **典型例子**: ```c struct Point { int x; int y; }; // 错误:重复初始化字段x struct Point p = { .x = 1, .x = 2, .y = 3 }; // 错误:乱序初始化(需按声明顺序) struct Point p = { .y = 2, .x = 1 }; // 需开启 -pedantic 触发 // 正确写法: struct Point p = { .x = 1, .y = 2 }; ``` --- ### 使用建议 1. **严格模式**:组合使用 `-Wall -Wextra -Wpedantic -Werror` 提升代码质量 2. **临时禁用**:对第三方代码用 `-Wno-error=xxx` 局部禁用 3. **应用场景**: - 嵌入式开发(内存安全) - 跨平台项目(类型严格检查) - 持续集成(确保零警告)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值