以下显然有效的代码使用UndefinedBehaviorSanitizer杀菌器产生错位的地址运行时错误。
#include <memory>
#include <functional>
struct A{
std::function<void()> data; // seems to occur only if data is a std::function
} ;
struct B{
char data; // occurs only if B contains a member variable
};
struct C:public virtual A,public B{
};
struct D:public virtual C{
};
void test(){
std::make_shared<D>();
}
int main(){
test();
return 0;
}
在macbook上编译和执行
clang++ -fsanitize=undefined --std=c++11 ./test.cpp && ./a.out
产生输出
runtime error: constructor call on misaligned address 0x7fe584500028 for type 'C', which requires 16 byte alignment [...]
。
我想了解错误的发生方式和原因。
答案 0 :(得分:5)
由于std::function<void()>
的对齐为16且大小为48,因此可以简化。此代码包含same behavior,但更容易理解:
struct alignas(16) A
{ char data[48]; };
struct B
{ char data; };
struct C : public virtual A, public B
{};
struct D : public virtual C
{};
int main()
{
D();
}
我们有以下对齐和尺寸:
|__A__|__B__|__C__|__D__|
alignment (bytes): | 16 | 1 | 16 | 16 |
size (bytes): | 48 | 1 | 64 | 80 |
现在让我们看看它在内存中的样子。关于这方面的更多解释可以在this great answer中找到。
char[48] + no padding == 48B
char[1] + no padding == 1B
A* + B + A + 7 bytes of padding (align to 16) == 64B
C* + C + 8 bytes of padding (align to 16) == 80B
现在很容易看到C
D
在C
内的偏移是8字节,但是00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
^
与16对齐。因此错误,这有助于这个伪 - 图形
D
这里每个零都是1个字节。
<强>更新强>:
填充的位置和方式取决于C ++编译器。标准没有指定它。它看起来像填充的大小,clang无法对齐if (isset($_POST['submit'])) {
$id = $_GET["section"];
$about_me = "../include/about_me.php";
$providers_2 = "../include/2providers.php";
$more_providers = "../include/more_proiders.php";
$section_change = $_POST["section_change"];
$query = "UPDATE sections SET ":
$query .= "`File Path` = '{$section_change}' ";
$query .= "WHERE id = '{$id}' ";
$query .= "LIMIT 1";
$result = mysqli_query($link, $query);
if ($result && mysqli_affected_rows($link) == 1) {
// Success
$_SESSION["message"] = "Section Changed.";
redirect_to("../index.php?admin=true");
} else {
// Failure
echo "System Failure. Please try again later. If problem persists please notify your admin at aqeke.com/powerplaylife-help"
}
}
else {
print_r( $_POST);
}
中的所有内容。缓解错位的一种方法是仔细设计类,使它们具有相同的对齐方式(例如,8个字节)。