Комментарии 4
хм, пойти чтоли eiskaltdcpp проверить, тематика та-же..
Если вкратце, то компилятор имеет полное право удалить вызовы memset, если посчитает их бессмысленными (такое часто происходит, когда буфер очищается в конце операции и более не используется). Удостовериться в том, что компиляторы действительно могут убрать ненужный вызов, можно с помощью проверки аналогичного кода сервисом Compiler Explorer.
Приведенный фрагмент кода не аналогичен. Transmission использует Glib и g_free
соответственно. Ни один компилятор не посчитает бессмысленым вызов memset
и не уберет его перед вызовом g_free
.
code
#include <stdlib.h>
#include <string.h>
#include <glib.h>
typedef void* gpointer;
typedef struct
{
char* target;
gpointer thereWereOtherElementsButTheyWereTruncatedForAnExample;
gpointer builder;
}
MakeMetaUI;
void doSomething(gpointer);
void freeMetaUI(gpointer p)
{
MakeMetaUI* ui = static_cast<MakeMetaUI*>(p);
doSomething(ui->builder);
g_free(ui->target);
memset(ui, ~0, sizeof(MakeMetaUI));
g_free(ui);
}
g++ `pkg-config --cflags --libs glib-2.0` test.cpp -O2 -masm=intel -S
output
.file "test.cpp"
.intel_syntax noprefix
.text
.p2align 4
.globl _Z10freeMetaUIPv
.type _Z10freeMetaUIPv, @function
_Z10freeMetaUIPv:
.LFB334:
.cfi_startproc
endbr64
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rdi
mov rdi, QWORD PTR 16[rdi]
call _Z11doSomethingPv@PLT
mov rdi, QWORD PTR 0[rbp]
call g_free@PLT
mov QWORD PTR 16[rbp], -1
pcmpeqd xmm0, xmm0
mov rdi, rbp
movups XMMWORD PTR 0[rbp], xmm0
pop rbp
.cfi_def_cfa_offset 8
jmp g_free@PLT
.cfi_endproc
.LFE334:
.size _Z10freeMetaUIPv, .-_Z10freeMetaUIPv
.ident "GCC: (Ubuntu 10.3.0-1ubuntu1~20.04) 10.3.0"
.section .note.GNU-stack,"",@progbits
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4:
clang++ `pkg-config --cflags --libs glib-2.0` test.cpp -O2 -masm=intel -S
output
.text
.intel_syntax noprefix
.file "test.cpp"
.globl _Z10freeMetaUIPv # -- Begin function _Z10freeMetaUIPv
.p2align 4, 0x90
.type _Z10freeMetaUIPv,@function
_Z10freeMetaUIPv: # @_Z10freeMetaUIPv
.cfi_startproc
# %bb.0:
push rbx
.cfi_def_cfa_offset 16
.cfi_offset rbx, -16
mov rbx, rdi
mov rdi, qword ptr [rdi + 16]
call _Z11doSomethingPv
mov rdi, qword ptr [rbx]
call g_free
pcmpeqd xmm0, xmm0
movdqu xmmword ptr [rbx], xmm0
mov qword ptr [rbx + 16], -1
mov rdi, rbx
pop rbx
.cfi_def_cfa_offset 8
jmp g_free # TAILCALL
.Lfunc_end0:
.size _Z10freeMetaUIPv, .Lfunc_end0-_Z10freeMetaUIPv
.cfi_endproc
# -- End function
.ident "Ubuntu clang version 11.1.0-++20210428103817+1fdec59bffc1-1~exp1~20210428204431.166"
.section ".note.GNU-stack","",@progbits
.addrsig
Я, возможно, не гуру теории программирования, но пояснения к "Фрагмент N4: неудачное явное приведение типа" меня как-то не удовлетворили. Я так понимаю, автор собирал библиотеки на 64-битной системе, где int имеет размер 32 бита, а size_t размер 64 бита. В этом случае объяснение и решение верное, но разве эра 32-битных ситем закончилась и их нигде и никак не осталось? Может быть это уже можно считать верным для десктопа, но для встраиваемых систем это точно вряд ли. Как я понимаю, на 32-битных ситсемах размер size_t будет те же 32 бита, а тогда ни о каком решении проблемы переполнения речи нет.
Проверка BitTorrent в честь 20-летнего юбилея. Время == качество