Auf Beendigung des letzten Threads warten...
-
@EinNutzer0 sagte in Auf Beendigung des letzten Threads warten...:
handles[(i - 1) / 2]
Erklär mal. Und nach der Erklärung, probier auch einmal aus, ob deine Annahmen überhaupt stimmen.
-
Das sollte, wegen
i += 2
so passen (wenn auch nicht sehr schön).Aber das Programm hat wegen der Übergabe von
&s
(lokale Variable) an die Thread-Funktion undefiniertes Verhalten:string s = string(argv[i]); int sleepTime = atoi(argv[i + 1]); DWORD myThreadID; handles[(i - 1) / 2] = CreateThread(0, 0, myThread, &s, 0, &myThreadID); this_thread::sleep_for(chrono::seconds(sleepTime));
Durch den 'sleep_for' wird zwar das Timing ein bißchen abgemildert, aber garantiert ist es nicht, daß die Thread-Funktion auch rechtzeitig aufgerufen wird und der Parameter bei
std::string s = *((std::string*)lpParameter);
korrekt übernommen wird (das erklärt dann wohl auch das Verhalten bei
sleepTime = 0
).
Warum überhaupt die Konvertierung zu einemstd::string
? Einfachargv[i]
übergeben (hier ist garantiert, daß diese Arraywerte während dermain
-Funktion erhalten bleiben).PS:
int n1 = (argc - 1) / 2; HANDLE handles[n1];
d.h. die Benutzung von VLA ist kein Standard-C++.
-
Naja, das argc ist eh wackelig.
Was, wenn 1 Argument übergeben wird, d.h. argc==2.Dann: n1 == (2-1)/2 == 1/2 == 0
VLAs der Größe 0 sind doch nicht erlaubt, oder? Aber auch egal, denn:
for (int i = 1; i < argc; i += 2)
ist dann1 < 2
im ersten Durchlauf, also true, und dann crasht es eben danach - sowohl beimatoi(argv[i + 1]);
als auch beimhandles[0] = ...
.
-
Vielen Dank für eure Ideen und Vorschläge, ich werde das nachher miteinbeziehen und eine neue Version posten. @SeppJ Sorry, dass ich dich angemault hatte, das wollte ich nicht.
Schönen Abend.
-
Btw. die eigene, ausführbare exe Datei kreidet mir Windows als Virus an, wenn ich sie ins Internet hochladen, und wieder herunterladen möchte, und verhindert den kompletten Download... Virustotal meldet "sauber".
Was ist so brisant an diesen Code?
Kann man in diesem Forum einen Dateianhang hinzufügen?
-
@EinNutzer0 sagte in Auf Beendigung des letzten Threads warten...:
kreidet mir Windows als Virus an
Genaue Meldung? Copy&Paste.
-
@EinNutzer0 sagte in Auf Beendigung des letzten Threads warten...:
Kann man in diesem Forum einen Dateianhang hinzufügen?
Nein. Wenn es wirklich wichtig ist, kannst du einen externen Hoster nutzen und verlinken. Falls dein Plan ist, dass sich jemand deine Executable runterlädt oder gar ausführt: Das wird wahrscheinlich niemand tun.
-
@Swordfish sagte in Auf Beendigung des letzten Threads warten...:
Genaue Meldung? Copy&Paste.
Edit: Link
-
-
Posting here is generally a waste of time, since no one here truly works for Microsoft, especially the more technical security groups involved in the operation and support for Defender itself. We're all mostly either consumer volunteers or contract workers who provide first-level support for Microsoft's products.
Heißt auf Deutsch, der KI, Heuristik oder wie man es nennen möchte, gefällt nicht, was ich tue. Aber ich freue mich, meinen ersten eigenen Virus entworfen zu haben. (Sogar schwerwiegend...)
-
Jetzt funktioniert's, Freunde:
#include <windows.h> #include <iostream> #include <string> #include <chrono> #include <thread> DWORD WINAPI myThread(LPVOID lpParameter) { using namespace std; char* argv = *((char**)lpParameter); chrono::milliseconds ms1 = chrono::duration_cast<chrono::milliseconds>( chrono::system_clock::now().time_since_epoch()); SHELLEXECUTEINFO ShExecInfo = { 0 }; ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; ShExecInfo.hwnd = NULL; ShExecInfo.lpVerb = NULL; ShExecInfo.lpFile = argv; ShExecInfo.lpParameters = ""; ShExecInfo.lpDirectory = NULL; ShExecInfo.nShow = SW_SHOW; ShExecInfo.hInstApp = NULL; ShellExecuteEx(&ShExecInfo); WaitForSingleObject(ShExecInfo.hProcess, INFINITE); chrono::milliseconds ms2 = chrono::duration_cast<chrono::milliseconds>( chrono::system_clock::now().time_since_epoch()); cout << argv << " : "; cout << GetProcessId(ShExecInfo.hProcess) << " : "; cout << (ms2 - ms1).count() << " Milliseconds" << endl; return 0; } int main(int argc, char* argv[]) { if (argc <= 1 || argc % 2 != 1) { return 0; } using namespace std; const int n1 = (argc - 1) / 2; HANDLE handles[n1]; for (int i = 1; i < argc; i += 2) { int sleepTime = atoi(argv[i + 1]); DWORD myThreadID; handles[(i - 1) / 2] = CreateThread(0, 0, myThread, &argv[i], 0, &myThreadID); this_thread::sleep_for(chrono::seconds(sleepTime)); } WaitForMultipleObjects(n1, handles, TRUE, INFINITE); for (int i = 0; i < n1; i++) { CloseHandle(handles[i]); } return 0; }
War echt so, dass die garbage collection gegriffen hat... Btw. warum muss ich erst nach
char**
und dann nach*
casten? LPVOID, DWORD und WINAPI ist mir sehr suspekt.
-
@EinNutzer0 sagte in Auf Beendigung des letzten Threads warten...:
garbage collection
what?
@EinNutzer0 sagte in Auf Beendigung des letzten Threads warten...:
Btw. warum muss ich erst nach char** und dann nach * casten?
Warum übergibst du überhaupt
&argv[i]
und nichtargv[i]
?
-
@Swordfish sagte in Auf Beendigung des letzten Threads warten...:
Warum übergibst du überhaupt &argv[i] und nicht argv[i]?
Ja, das frage ich mich auch... Ich habe Teile von diesem myThread example aus einem Blog kopiert, ich glaube, derjenige wusste auch nicht bescheid...
-
Also, hier ist der Vollständigkeit halber noch mal das gesamte Programm:
#include <windows.h> #include <iostream> #include <string> #include <chrono> #include <thread> DWORD WINAPI myThread(LPVOID lpParameter) { using namespace std; char* argv = (char*)lpParameter; chrono::milliseconds ms1 = chrono::duration_cast<chrono::milliseconds>( chrono::system_clock::now().time_since_epoch()); SHELLEXECUTEINFO ShExecInfo = { 0 }; ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; ShExecInfo.hwnd = NULL; ShExecInfo.lpVerb = NULL; ShExecInfo.lpFile = argv; ShExecInfo.lpParameters = ""; ShExecInfo.lpDirectory = NULL; ShExecInfo.nShow = SW_SHOW; ShExecInfo.hInstApp = NULL; ShellExecuteEx(&ShExecInfo); WaitForSingleObject(ShExecInfo.hProcess, INFINITE); chrono::milliseconds ms2 = chrono::duration_cast<chrono::milliseconds>( chrono::system_clock::now().time_since_epoch()); cout << argv << " : "; cout << GetProcessId(ShExecInfo.hProcess) << " : "; cout << (ms2 - ms1).count() << " Milliseconds" << endl; return 0; } int main(int argc, char* argv[]) { if (argc <= 1 || argc % 2 != 1) { return 0; } using namespace std; const int n1 = (argc - 1) / 2; HANDLE handles[n1]; for (int i = 1; i < argc; i += 2) { int sleepTime = atoi(argv[i + 1]); DWORD myThreadID; handles[(i - 1) / 2] = CreateThread(0, 0, myThread, argv[i], 0, &myThreadID); this_thread::sleep_for(chrono::seconds(sleepTime)); } WaitForMultipleObjects(n1, handles, TRUE, INFINITE); for (int i = 0; i < n1; i++) { CloseHandle(handles[i]); } return 0; }
Es funktioniert, aber ist es auch schön?