我一直在查看 C 嚴格的別名規則,這讓我想到了我之前作業中的一些代碼。我相信說代碼違反了嚴格的別名規則,但很好奇為什么我們沒有遇到任何問題或編譯器警告。我們使用核心 .DLL 來接收傳遞給服務器應用程式的網路訊息。一個(非常)簡化的例子:
#include <iostream>
#include <cstring>
using namespace std;
// These enums/structs lived in a shared .h file consumed by the DLL and server application
enum NetworkMessageId : int
{
NETWORK_MESSAGE_LOGIN
// ...
};
struct NetworkMessageBase
{
NetworkMessageId type;
size_t size;
};
struct LoginNetworkMessage : NetworkMessageBase
{
static constexpr size_t MaxUsernameLength = 25;
static constexpr size_t MaxPasswordLength = 50;
char username[MaxUsernameLength];
char password[MaxUsernameLength];
};
// This buffer and function was created/exported by the DLL
char* receiveBuffer = new char[sizeof(LoginNetworkMessage)];
NetworkMessageBase* receiveNetworkMessage()
{
// Simulate receiving data from network, actual production code provided additional safety checks
LoginNetworkMessage msg;
msg.type = NETWORK_MESSAGE_LOGIN;
msg.size = sizeof(msg);
strcpy(msg.username, "username1");
strcpy(msg.password, "qwerty");
memcpy(receiveBuffer, &msg, sizeof(msg));
return (NetworkMessageBase*)&receiveBuffer[0]; // I believe this line invokes undefined behavior (strict aliasing)
}
// Pretend main is the server application
int main()
{
NetworkMessageBase* msg = receiveNetworkMessage();
switch (msg->type)
{
case NETWORK_MESSAGE_LOGIN:
{
LoginNetworkMessage* loginMsg = (LoginNetworkMessage*)msg;
cout << "Username: " << loginMsg->username << " Password: " << loginMsg->password << endl;
}
break;
}
delete [] receiveBuffer; // A cleanup function defined in the DLL actually did this
return 0;
}
據我了解,receiveNetworkMessage()呼叫未定義的行為。我讀過嚴格的別名 UB 通常與編譯器優化/假設有關。我認為這些優化與這種情況無關,因為 .DLL 和服務器應用程式是分開編譯的。那是對的嗎?
最后,客戶端應用程式還共享了提供的示例 .h,它用于創建一個LoginNetworkMessage逐位元組流式傳輸到服務器的示例。這是便攜的嗎?撇開包裝/位元組順序問題不談,我相信這不是因為LoginNetworkMessage' 的布局是非標準的,所以成員排序可能會有所不同。
uj5u.com熱心網友回復:
據我了解,receiveNetworkMessage() 呼叫未定義的行為
正確的。
LoginNetworkMessage 逐位元組流式傳輸到服務器。這是便攜的嗎?
不,依賴二進制兼容性的網路通信不可移植。
除了打包/位元組序問題,我相信這不是因為 LoginNetworkMessage 的布局是非標準的,所以成員排序可能會有所不同。
即使對于非標準布局類,成員的順序也得到保證。問題(除了位元組序)是用于對齊目的的填充的數量和位置、基本型別的大小、位元組中的位數(盡管公平地說,非 8 位位元組的網路連接硬體可能不是你需要支持的東西)。
uj5u.com熱心網友回復:
我認為這些優化與這種情況無關,因為 .DLL 和服務器應用程式是分開編譯的。那是對的嗎?
是的。這使得代碼在實踐中是安全的(即使標準不知道任何 DLL 并且無論如何都認為它未定義)。
對于不同的翻譯單元也是如此,除非啟用了整體程式優化。
正如另一個答案所說,這里唯一的潛在問題是結構布局的可移植性。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/407214.html
標籤:
上一篇:是按值傳遞指標還是按參考傳遞相同
下一篇:復制繼承類的指標向量的問題
