分享奇异BUG一枚

「已注销」 2014-12-19 02:04:43
最近本人搞了搞用户线程(协程),出现了一个奇异错误,当然,错误已经排除。

但因为它很隐晦,跟大家分享一下。凡试猜者都有分,第一个猜中谜底者得100分,其他分均分。


#include <windows.h>

typedef struct ucontext
{
CONTEXT thread_context;
}
ucontext_t;

int getcontext( ucontext_t *a )
{
int ret;
a->thread_context.ContextFlags = CONTEXT_FULL;
ret = GetThreadContext(GetCurrentThread(), &a->thread_context) ? 0 : -1;
return ret;
}

int setcontext( ucontext_t *a )
{
return SetThreadContext(GetCurrentThread(), &a->thread_context) ? 0 : -1;
}

int swapcontext( ucontext_t *a, ucontext_t *b )
{
int ret;
if((ret = getcontext(a)) == 0)
ret = setcontext(b);
return ret;
}


PS:
1. BUG就在这些代码里,而不是在别处。
2. 如果有笔误,是可能的,因为代码是我刚打的,不是工程里的真实代码,仅为说明问题。

...全文
1189 55 打赏 收藏 转发到动态 举报
写回复
用AI写文章
55 条回复
切换为时间正序
请发表友善的回复…
发表回复
qwer_boo 2014-12-22
  • 打赏
  • 举报
回复
楼主很牛逼!
「已注销」 2014-12-21
  • 打赏
  • 举报
回复
引用 50 楼 bug1190 的回复:
一个SB在这B叫而己 Remarks The GetThreadContext function is used to retrieve the context of the specified thread. The function allows a selective context to be retrieved based on the value of the ContextFlags member of the CONTEXT structure. The thread handle identified by the hThread parameter is typically being debugged, but the function can also operate when it is not being debugged. You cannot get a valid context for a running thread. Use the SuspendThread function to suspend the thread before calling GetThreadContext. If you call GetThreadContext for the current thread, the function returns successfully; however, the context returned is not valid.
像你这种没教养的东西,我不愿意理你,自己滚蛋。
「已注销」 2014-12-21
  • 打赏
  • 举报
回复
引用 45 楼 fly_dragon_fly 的回复:
int  getcontext( ucontext_t *a )
{
      int ret;
      a->thread_context.ContextFlags = CONTEXT_FULL;
      ret = GetThreadContext(GetCurrentThread(), &a->thread_context) ? 0 : -1;
      return ret;
}
这个ret会导致占用栈空间4字节,而set的时候没有这个消耗,当切换回来a时,两边栈就不平衡,导致返回地址无效了。
这是正确答案。 这位兄弟肯定搞过类似的工作吧?
w74839520 2014-12-20
  • 打赏
  • 举报
回复
楼上的分析很精辟。
fly_dragon_fly 2014-12-20
  • 打赏
  • 举报
回复
int  getcontext( ucontext_t *a )
{
      int ret;
      a->thread_context.ContextFlags = CONTEXT_FULL;
      ret = GetThreadContext(GetCurrentThread(), &a->thread_context) ? 0 : -1;
      return ret;
}
这个ret会导致占用栈空间4字节,而set的时候没有这个消耗,当切换回来a时,两边栈就不平衡,导致返回地址无效了。
loong0306 2014-12-20
  • 打赏
  • 举报
回复
难道是 多进程?无限刷内存?。。
huanglin03 2014-12-20
  • 打赏
  • 举报
回复
You cannot get a valid context for a running thread. Use the SuspendThread function to suspend the thread before calling GetThreadContext. If you call GetThreadContext for the current thread, the function returns successfully; however, the context returned is not valid. 是你说可以不停就可以切换是吧,MSDN上的这段话怎么跟你说的完全相反呢
line_us 2014-12-20
  • 打赏
  • 举报
回复
只看看状况和分析
lm_whales 2014-12-20
  • 打赏
  • 举报
回复
#include <windows.h> typedef struct ucontext { CONTEXT thread_context; } ucontext_t; int getcontext( ucontext_t *a ) { int ret; a->thread_context.ContextFlags = CONTEXT_FULL; ret = GetThreadContext(GetCurrentThread(), &a->thread_context) ? 0 : -1; //GetThreadContext 获取的是此处的上下文,不是调用 getcontext 的调用点的上下文,切换回来以后,这部分//GetThreadContext有可能重新执行,或者在 //GetThreadContext 函数内部某点执行。 return ret; } int setcontext( ucontext_t *a ) { return SetThreadContext(GetCurrentThread(), &a->thread_context) ? 0 : -1; } int swapcontext( ucontext_t *a, ucontext_t *b ) { int ret; if((ret = getcontext(a)) == 0) ret = setcontext(b); return ret; } int swapcontext( ucontext_t *a, ucontext_t *b ) { int ret; a->thread_context.ContextFlags = CONTEXT_FULL; if( (ret = (GetThreadContext(GetCurrentThread(), &a->thread_context) ? 0 : -1) == 0 ) ret = SetThreadContext(GetCurrentThread(), &b->thread_context) ? 0 : -1; //切换点在这个函数内部执行 return ret; }
卖水果的net 2014-12-20
  • 打赏
  • 举报
回复
看 了半天回复,也不懂。。。
聚义舔刀 2014-12-19
  • 打赏
  • 举报
回复
我猜GetCurrentThread()的值有问题
draculamx 2014-12-19
  • 打赏
  • 举报
回复
来围观,只做过多线程的初级应用。。。。
mark_work 2014-12-19
  • 打赏
  • 举报
回复
围观的~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  • 打赏
  • 举报
回复
你对当前线程SetThreadContext,那么可能会影响到当前线程的执行栈,下一条语句都不知道去哪了,因此可能出现各种奇异情况: if (SetThreadContext(当前线程)) {    在这里写代码很可能是没有任何意义的 } --- SetThreadContext一般都是用来搞其他线程的,搞自己的时候真不多
赵4老师 2014-12-19
  • 打赏
  • 举报
回复
引用 30 楼 sinservice 的回复:
[quote=引用 28 楼 zhao4zhong1 的回复:] 《30天自制操作系统》
在linus之前,全世界只有5个人独自设计并实现了操作系统,linus是第6个。 我根本不相信这种自制操作系统的说法。 我用8051汇编写个电子秤的程序,那的确是运行在纯粹硬件上的直接接触硬件的软件,但我不认为那就是操作系统。 [/quote] 你的成见阻挡了你学习提高的前路。 搜“空杯心态”
「已注销」 2014-12-19
  • 打赏
  • 举报
回复
引用 38 楼 luciferisnotsatan 的回复:
windows不有个协程么?CreateFiberEx 不能满足lz需求?
windows fiber限制很大,最多只能建立2000多个,太少了,不够用的。
luciferisnotsatan 2014-12-19
  • 打赏
  • 举报
回复
windows不有个协程么?CreateFiberEx 不能满足lz需求?
「已注销」 2014-12-19
  • 打赏
  • 举报
回复
引用 36 楼 fly_dragon_fly 的回复:
ret = setcontext(b); 在切换线程后,这个context是否把当前的esp也换掉了,导致ret的地址无效了,
有门了,但不对。 你看29L,那样写就可以。
fly_dragon_fly 2014-12-19
  • 打赏
  • 举报
回复
ret = setcontext(b); 在切换线程后,这个context是否把当前的esp也换掉了,导致ret的地址无效了,
FightForProgrammer 2014-12-19
  • 打赏
  • 举报
回复
getcontext setcontext 用这两个函数都是从主线程的栈中调用GetThreadContext、SetThreadContext。返回的时候作为协程会不会。。。不知道!~~~
加载更多回复(34)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧