admin管理员组文章数量:1194732
I have this source code:
#include <iostream>
#include <cstdint>
#include <cstring>
struct bt_data {
uint8_t type;
uint8_t data_len;
const uint8_t* data;
};
static const char* devName="LSM6DSR_Sensor";
bt_data ad[] = {
{ .type = (0x01), .data_len = (sizeof((uint8_t []) { (0x02 | 0x04) })), .data = (const uint8_t *)(((uint8_t []) { (0x02 | 0x04) })), },
{ .type = (0x09), .data_len = (strlen(devName)-1), .data = (const uint8_t *)(devName), },
};
int main() {
uint8_t d1[] { (0x02 | 0x04) };
bt_data ad3[] = {
{ .type = (0x01), .data_len = 1, .data = d1, },
{ .type = (0x09), .data_len = 14, .data = (const uint8_t *)devName, },
};
bt_data ad2[] = {
{ .type = (0x01), .data_len = (sizeof((uint8_t []) { (0x02 | 0x04) })), .data = (const uint8_t *)(((uint8_t []) { (0x02 | 0x04) })), },
{ .type = (0x09), .data_len = (strlen(devName)-1), .data = (const uint8_t *)(devName), },
};
std::cout << "global: " << sizeof(ad) / sizeof(ad[0]) << " " << ad[1].data << std::endl;
std::cout << "local, extra: " << sizeof(ad3) / sizeof(ad3[0]) << " " << ad3[1].data << std::endl;
std::cout << "local temp: " << sizeof(ad2) / sizeof(ad2[0]) << " " << ad2[1].data << std::endl;
}
it allocates different arrays of variable size in local and global scope. Note in particular, that the definition of ad
and ad2
is exactly the same, but ad
is in global scope.
The program output of GCC 12.2.0 is :
Program returned: 0
global: 2 LSM6DSR_Sensor
local, extra: 2 LSM6DSR_Sensor
local temp: 1
When running with GCC 14, I get this:
Program returned: 0
global: 2 LSM6DSR_Sensor
local, extra: 2 LSM6DSR_Sensor
local temp: 2 LSM6DSR_Sensor
Clang warns for ad2
that the temporary array is destroyed at the end of the expressions.
Question:
- Why is the temporary array not destroyed in the global scope?
- Does this depend on a particular C++ standard? Would it be different in C language, also for the local array?
I have this source code:
#include <iostream>
#include <cstdint>
#include <cstring>
struct bt_data {
uint8_t type;
uint8_t data_len;
const uint8_t* data;
};
static const char* devName="LSM6DSR_Sensor";
bt_data ad[] = {
{ .type = (0x01), .data_len = (sizeof((uint8_t []) { (0x02 | 0x04) })), .data = (const uint8_t *)(((uint8_t []) { (0x02 | 0x04) })), },
{ .type = (0x09), .data_len = (strlen(devName)-1), .data = (const uint8_t *)(devName), },
};
int main() {
uint8_t d1[] { (0x02 | 0x04) };
bt_data ad3[] = {
{ .type = (0x01), .data_len = 1, .data = d1, },
{ .type = (0x09), .data_len = 14, .data = (const uint8_t *)devName, },
};
bt_data ad2[] = {
{ .type = (0x01), .data_len = (sizeof((uint8_t []) { (0x02 | 0x04) })), .data = (const uint8_t *)(((uint8_t []) { (0x02 | 0x04) })), },
{ .type = (0x09), .data_len = (strlen(devName)-1), .data = (const uint8_t *)(devName), },
};
std::cout << "global: " << sizeof(ad) / sizeof(ad[0]) << " " << ad[1].data << std::endl;
std::cout << "local, extra: " << sizeof(ad3) / sizeof(ad3[0]) << " " << ad3[1].data << std::endl;
std::cout << "local temp: " << sizeof(ad2) / sizeof(ad2[0]) << " " << ad2[1].data << std::endl;
}
it allocates different arrays of variable size in local and global scope. Note in particular, that the definition of ad
and ad2
is exactly the same, but ad
is in global scope.
The program output of GCC 12.2.0 is :
Program returned: 0
global: 2 LSM6DSR_Sensor
local, extra: 2 LSM6DSR_Sensor
local temp: 1
When running with GCC 14, I get this:
Program returned: 0
global: 2 LSM6DSR_Sensor
local, extra: 2 LSM6DSR_Sensor
local temp: 2 LSM6DSR_Sensor
Clang warns for ad2
that the temporary array is destroyed at the end of the expressions.
Question:
- Why is the temporary array not destroyed in the global scope?
- Does this depend on a particular C++ standard? Would it be different in C language, also for the local array?
1 Answer
Reset to default 01. Why is the temporary array not destroyed in the global scope?
Since it is in global scope, it won't be destroyed until after main
returns.
2a. Does this depend on a particular C++ standard?
The C++ standard won't matter. The compiler and its version will matter, as demonstrated with GCC.
Destruction is not guaranteed to happen at a specific time. The standard only says the destruction will occur sometime after it leaves scope, as determined by the compiler implementation.
2b. Would it be different in C language, also for the local array?
C doesn't have destructors. When you leave main
, all the memory is left as it was for the OS to reuse.
Additional Thoughts
I wouldn't trust the output counts. Instrumenting constructors and destructors might provide meaningful information. I didn't do it because designated initializers cannot be used with constructors present.
I copied the code to Compiler Explorer and got many errors since I compiled it with -Wall
, -Wpedantic
, and -Werror
. After removing those, I got the same results as you with different versions of CLang and GCC. Given all the errors, I wouldn't trust this code in production.
It bothered me that there was no output from ad3[1].data
. On a whim, I replaced the division with std::size
. The size is the same, except a garbled name is output. With the division the output stops after the output of the space. I guess data
contains a null character, which shuts down the output to std::cout
, but why does it work with size
? I don't have a clue.
Ha! Rerunning it with GCC 12.2 outputs a garbled name. Here's the Compiler Explorer version.
本文标签: cUndefined behaviour Local vs global scope and pointer to temporary arrayStack Overflow
版权声明:本文标题:c++ - Undefined behaviour? Local vs global scope and pointer to temporary array - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738424389a2086039.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
ad[0]
andad2[0]
have pointers to dangling temporaries but this shouldn't invoke UB if you never access them, changing the first row tonullptr
instead of(const uint8_t *)(((uint8_t []) { (0x02 | 0x04) }))
fixes the issue, so it is likely gcc bugged out due to all the illegal C casts of temporaries that could result in reading undefined stack memory that doesn't exist when constructing the object ... maybe gcc optimized out the first row when it realized it was UB to use it anyway ?! – Ahmed AEK Commented Jan 24 at 11:57ad[0]
which has a dangling pointer, and AFAIK using it is UB any all C and C++ standards. – Ahmed AEK Commented Jan 24 at 12:04ad3
, never doad1
orad2
– Ahmed AEK Commented Jan 24 at 12:41