Странное поведение компилятора Intel C++?

При разборе одного рабочего проекта столкнулся со странной проблемой: отладочная версия «падала» с ошибкой «Run-Time Check Failure #0 — The value of ESP was not properly saved across a function call».

Стал разбираться…


Пришел к вот такому коду, который падает абсолютно по той же причине:
#include <string.h>
void test()
{
	char a[10];
	char b[] = "test";
	strcpy_s(a, b);
	__try
	{
	}
	__except(1)
	{
	}
}
int main()
{
	test();
	return 0;
}



Компилятор:

Intel® C++ Compiler for applications running on IA-32, Version 10.0 Build 20070426 Package ID: W_CC_P_10.0.025


Командная строка:

icl /c /Od /RTC1 /MDd /Gd main.cpp

xilink main.obj


После разбора того, во что это всё компилируется, нашлась вот такая проблема: при вызове функции test() выделяется сразу вся нужная память на стеке, esp сохраняется в стек, вызывается strcpy_s, esp увеличиваем на 8(освобождаем стековую память), восстанавливаем сохраненный esp, esp увеличиваем на объем выделенной памяти в начале, сравниваем esp с ebp -> Ошибка!


Листинг получился такой(оставлено только нужное место):
push      -1
push      OFFSET FLAT: _try_info_pack0
push      OFFSET FLAT: __except_handler3
push      eax
sub       esp, 3Ch
mov       DWORD PTR [ebp - 18h], esp
add       esp, 0
call      strcpy_s
add       esp, 8
mov       esp, DWORD PTR [ebp - 18h]
add       esp, 44h
cmp       ebp, esp
call      __RTC_CheckEsp



т.е. аналогия такая:

push eax;
mov dword ptr[ebp - 18h], esp;
pop eax;
mov esp, dword ptr[ebp - 18h];
cmp esp, ebp; // !!!!



Проблема решилась вот таким образом: в самое начало функции test() можно добавить такую вставку:
__asm
{
	nop;
}



После этого ошибка пропадает, из листинга тоже видно, что код теперь корректен(стековая память выделяется перед вызовом strcpy_s, освобождается сразу после):
push      -1
push      OFFSET FLAT: _try_info_pack0
push      OFFSET FLAT: __except_handler3
push      eax
sub       esp, 34h
mov       DWORD PTR [ebp - 18h], esp
add       esp, -8
call      strcpy_s
add       esp, 8
mov       esp, DWORD PTR [ebp - 18h]
add       esp, 44h
cmp       ebp, esp
call      __RTC_CheckEsp



т.е. аналогия такая:

mov dword ptr[ebp - 18h], esp;
push eax;
pop eax;
mov esp, dword ptr[ebp - 18h];
cmp esp, ebp; // Теперь всё хорошо



Думается мне, что это ошибка компилятора? Или ошибка закралась где-то у меня в коде?


P.S.

В версии компилятора 11.1.035 компилируется корректно, т.е. есть подозрение, что это именно косяк в компиляторе.

Added:

Следующий код падает по той же причине(при вызове любой функции, аргументы которой передаются через стек):
void t2(int a)
{
	return;
}
void t1()
{
	t2(10);
	__try
	{
	}
	__except(1)
	{
	}
}
int main()
{
	t1();
	return 0;
}
  • Вопрос задан
  • 4479 просмотров
Пригласить эксперта
Ответы на вопрос 1
Paul
@Paul
Похоже на косяк компилятора. У вас Intel Compiler куплен? Напишите в саппорт.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы