Some time ago, I developed a small Windows tool to measure how long a thread took to test an external device. The project intrigued me due to a particularly tricky bug that took me over an hour to resolve. During that time, I consulted ChatGPT for assistance, but it failed to provide useful solutions.
Today, I decided to try DeepSeek instead. I
copied the same question I had asked ChatGPT, and amusingly, DeepSeek delivered
the correct answer after just 137 seconds of processing. From now on, I’ll be
making DeepSeek my first go-to resource for troubleshooting.
In this article, I’ll share the problem I
encountered, how I ultimately solved it, and—of course—the first time and correct answer
provided by DeepSeek.
Question (to ChatGPT and DeepSeek):
This is Visual C++ Win32 MFC application, why following function
got GUI update with "Multicast stopped: 57730ms, sent 0 frames":
void threadFunction()
{
// Record
the start time using high-resolution clock
auto startTime = std::chrono::high_resolution_clock::now();
int nSentCount = 0;
// thread
running ..., std::this_thread::sleep_for(std::chrono::seconds(2));
//
nSentCount++; // Increment the sent count
auto endTime = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
CString
info;
if (nSentCount > 1) info.Format(_T("Multicast stopped: %ldms, sent %ld frames"), duration, nSentCount);
else info.Format(_T("Multicast
stopped"));
pView->UpdateScreenInfo(EVENT_INFO, info);
}
Troubleshooting
Yes, I was shocked by the result—I couldn’t
believe what I was seeing. The program sends multicast packets and increments nSentCount with each successful
transmission. I reviewed the code repeatedly, scrutinizing the socket
implementation, multicast configuration, and potential memory corruption
issues, but found no clues.
Frustrated, I turned to ChatGPT. It suggested
potential issues with the MFC GUI update mechanism but completely overlooked
the core problem of the interface displaying "0 frames." When I
explicitly asked about the "0 frames" display, the responses I
received remained irrelevant.
1. Initialize nSentCount Appropriately: …
2. Review Modifications to nSentCount: …
3. Implement Logging: …
Eventually, I narrowed my focus to the CString implementation. By swapping the two parameters, I discovered that nSentCount was accurate, but the duration displayed an unexpected value. To verify this, I tested the behavior using the following source code:
int main()
{
long long
duration = 1234567890;
int
nSentCount = 321;
printf("test printf with ld: %ldms, sent %ld frames\n", duration,
nSentCount);
printf("test printf with lld: %lldms,
sent %ld frames\n", duration, nSentCount);
return 0;
}
Compile and run:
test printf with ld:
2123683780ms, sent 1234567890 frames --- wrong
test printf with lld:
1234567890ms, sent 321 frames --- correct
DeepSeek’s Answer
The issue arises due to a combination of incorrect UI thread access and logical errors in your code. Here's the breakdown and solution:
UI Update from Worker Thread:
Problem: MFC requires GUI updates to occur on the main UI thread. Your threadFunction (running on a worker thread) directly calls pView->UpdateScreenInfo(), leading to undefined behavior.
Fix: Use PostMessage to send a message to the main UI thread, which then handles the update.
Incorrect Format String Condition:
Problem: The message shows details even when nSentCount is 0. Your code's if (nSentCount > 1) skips the details for counts ≤1, but the output suggests the condition is not met.
Fix: Check if nSentCount > 0 instead to include single-frame sends.
Uncommented Work Simulation:
Problem: The sleep and increment are commented, so nSentCount remains 0, and duration is negligible. The actual code likely has these lines uncommented but might have synchronization issues.
Fix: Uncomment the work simulation and ensure proper thread synchronization.
Corrected Code:
// In your worker thread
function
void threadFunction()
{
auto startTime = std::chrono::high_resolution_clock::now();
int nSentCount = 0;
// Simulate work (uncommented)
std::this_thread::sleep_for(std::chrono::seconds(2));
nSentCount++; // Increment sent
count
auto endTime = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
// Post message to UI thread
CString
info;
if (nSentCount > 0)
info.Format(_T("Multicast
stopped: %lldms, sent %d frames"), duration, nSentCount);
else
info = _T("Multicast
stopped");
// Assuming pView is a valid pointer and you have a custom message handler
::PostMessage(pView->GetSafeHwnd(), WM_UPDATE_UI, (WPARAM)EVENT_INFO,
(LPARAM)new CString(info));
}
// In your view class
header (e.g., CMyView.h)
#define WM_UPDATE_UI (WM_USER + 1)
afx_msg LRESULT
OnUpdateUI(WPARAM wParam, LPARAM lParam);
// In your view class implementation (e.g., CMyView.cpp)
BEGIN_MESSAGE_MAP(CMyView,
CView)
ON_MESSAGE(WM_UPDATE_UI, OnUpdateUI)
END_MESSAGE_MAP()
LRESULT CMyView::OnUpdateUI(WPARAM wParam, LPARAM lParam)
{
EventType
type = static_cast<EventType>(wParam);
CString*
pInfo = reinterpret_cast<CString*>(lParam);
UpdateScreenInfo(type, *pInfo);
delete pInfo; // Clean up the
allocated string
return 0;
}
Key Changes:
UI Thread Safety: Uses PostMessage to marshal data to the UI thread.
Condition Check: Updates the condition to nSentCount > 0 to handle single frames.
Correct Format Specifiers: Uses %lld for duration (64-bit integer) and %d for nSentCount.
Memory Management: Allocates CString dynamically to prevent stack corruption.
Additional Checks:
Ensure pView is valid and not destroyed before the message is processed.
Handle thread synchronization if threadFunction runs multiple times or in a loop.
What lesson we learned (by DeepSeek)
Your experience is a microcosm of software engineering: even "trivial" code can harbor insidious bugs, and rigor (in testing, tooling, and humility) is the antidote. Celebrate the solve – it’s these battles that keep the craft alive and rewarding. 🛠
你的这段经历是软件工程的缩影:即便是“看似简单”的代码,也可能暗藏隐蔽的缺陷,而唯有通过严谨(测试、工具链和谦逊的态度)才能将其化解。庆祝这次问题的解决吧——正是这些战斗,让这门技艺永葆活力并充满回报。️
No comments:
Post a Comment