Области видимости функций в Си
Пишу на Си, с использованием тулкита edk2, от tianocore. Наличествует функция - оболочка, вызывающая иные функции и обрабатывающая коды возврата. Приведённая ниже конструкция отрабатывает некорректно, и мне банально не хватает знаний установить причину:
Status = StartTesting(ConfigName, TestsCount, TestList, &ImageHandle, &Result);
if (EFI_ERROR(Status))
{
StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_ERR.log");
WriteLog(Log);
SaveLog(LogFileName, ConfigName, ImageHandle);
}
else if (Result)
{
StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_PASS.log");
WriteLog(Log);
SaveLog(LogFileName, ConfigName, ImageHandle);
Print(L"Inner var:%d %r\n", Status, Status);
}
else
{
StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_FAIL.log");
WriteLog(Log);
SaveLog(LogFileName, ConfigName, ImageHandle);
Status = EFI_NOT_FOUND;
}
Print(L"Outer var:%d %r\n", Status, Status);
return Status;
Некорректность заключается в том, что код выполнения всей функции (Status) содержит в себе случайную область памяти - не прогнозируемое значение, а всякий мусор.
При этом, Print(L"Inner var:%d %r\n", Status, Status); выдаст ожидаемое Inner var:0 Success, а Print(L"Outer var:%d %r\n", Status, Status); уже выдаёт Outer var:7077934 006C002E, тогда как по логике работы программы они должны быть идентичны.
Возможно кто-то встречался с аналогичной проблемой, или имеет более глубокий уровень понимания области видимости, чтобы что-то мне подсказать.
Уточнение: Полный контекст функции привожу ниже. Минимальный воспроизводимый код в данных условиях невозможен, так как требует передачи всех функций. Как видно, Status не является глобальной, Status многократно переопределяется и обрабатывается в процессе работы, при этом указанные ошибки проявляются только в участках вывода кода программы, в областях, где присутствует return.
***
28 EFI_STATUS StartTesting(IN CHAR16*, IN UINTN, IN CHAR8[][KEY_MAX_SIZE], IN EFI_HANDLE*, OUT BOOLEAN*);
***
33 EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
34 {
35 EFI_STATUS Status;
36 BOOLEAN Result;
37 CHAR16 LogFileName[LOGFILE_NAME_MAX_SIZE];
38 CHAR8 Temp[LOGFILE_NAME_MAX_SIZE];
39 CHAR16 ConfigName[CONFIG_NAME_MAX_SIZE] = {0};
40 UINTN TestsCount;
41
42 Status = GetConfigData(Log, "SN", L"\\current.log", Temp);
43 if (EFI_ERROR(Status))
44 {
45 Print(L"\nCan not create logfile: %r\n", Status);
46 return Status;
47 }
48
49 Trim(Temp);
50 UnicodeSPrint(LogFileName, sizeof(CHAR16) * (AsciiStrLen(Temp) + 1), L"%a", Temp);
51
52 Status = GetArgs(&ImageHandle, ConfigName);
53 if (Status == EFI_INVALID_PARAMETER) //Статус-код EFI_INVALID_PARAMETER говорит о том, что опций запуска нет.
54 {
55 Status = SetArgs(ConfigName);
56 if (EFI_ERROR(Status))
57 {
58 StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_ERR.log");
59 WriteLog(Log);
60 SaveLog(LogFileName, L"Unknown", ImageHandle);
61 return Status;
62 }
63 }
64 else if (EFI_ERROR(Status))
65 {
66 StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_ERR.log");
67 WriteLog(Log);
68 SaveLog(LogFileName, L"Unknown", ImageHandle);
69 return Status;
70 }
71
72 Status = CheckConfig(ConfigName, &TestsCount); //Проверяем, есть ли нужный конфиг-файл. Если есть, то возвращаем количество тестов, указанных в нём. Если нет -- 0. Status -- ошибки чтения/записи файла.
73 if (EFI_ERROR(Status))
74 {
75 StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_ERR.log");
76 WriteLog(Log);
77 SaveLog(LogFileName, ConfigName, ImageHandle);
78 return Status;
79 }
80
81 if (!TestsCount)
82 {
83 Status = CreateConfig(ConfigName, ImageHandle);
84 if (EFI_ERROR(Status))
85 {
86 StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_ERR.log");
87 WriteLog(Log);
88 SaveLog(LogFileName, ConfigName, ImageHandle);
89 return Status; //Программа возвращает код EFI_MEDIA_CHANGED когда создаёт конфиг-файл. После создания конфига необходимо выключить машину для установки "временных" устройств.
90 }
91 else
92 {
93 StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_CONF.log");
94 Status = EFI_MEDIA_CHANGED;
95 WriteLog(Log);
96 SaveLog(LogFileName, ConfigName, ImageHandle);
97 return Status; //Программа возвращает код EFI_MEDIA_CHANGED когда создаёт конфиг-файл. После создания конфига необходимо выключить машину для установки "временных" устройств.
98 }
99 }
100
101 CHAR8 TestList[TestsCount][KEY_MAX_SIZE];
102 Status = CreateTestList(ConfigName, TestsCount, TestList);
103 if (EFI_ERROR(Status))
104 {
105 StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_ERR.log");
106 WriteLog(Log);
107 SaveLog(LogFileName, ConfigName, ImageHandle);
108 return Status;
109 }
110
111 if (EFI_ERROR(ShellFileExists(ConfigName)))
112 {
113 MoveConfig(ConfigName, &ImageHandle);
114
115 Status = AddTempConfig(ConfigName, TestsCount, TestList, &ImageHandle);
116 if (EFI_ERROR(Status))
117 {
118 StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_ERR.log");
119 WriteLog(Log);
120 SaveLog(LogFileName, ConfigName, ImageHandle);
121 return Status;
122 }
123
124 Status = RewriteStartup(ConfigName);
125 if (EFI_ERROR(Status))
126 {
127 StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_ERR.log");
128 WriteLog(Log);
129 SaveLog(LogFileName, ConfigName, ImageHandle);
130 return Status;
131 }
132 }
133
134 Status = StartTesting(ConfigName, TestsCount, TestList, &ImageHandle, &Result);
135 if (EFI_ERROR(Status))
136 {
137 StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_ERR.log");
138 WriteLog(Log);
139 SaveLog(LogFileName, ConfigName, ImageHandle);
140 }
141 else if (Result)
142 {
143 StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_PASS.log");
144 WriteLog(Log);
145 SaveLog(LogFileName, ConfigName, ImageHandle);
146 Print(L"Inner var:%d %r\n", Status, Status);
147 }
148 else
149 {
150 StrCatS(LogFileName, LOGFILE_NAME_MAX_SIZE, L"_FAIL.log");
151 WriteLog(Log);
152 SaveLog(LogFileName, ConfigName, ImageHandle);
153 Status = EFI_NOT_FOUND;
154 }
155
156 Print(L"Outer var:%d %r\n", Status, Status);
157 return Status;
158 }