Is a goto in alloca's function scope valid?

浪子不回头ぞ 提交于 2019-12-23 07:29:26

问题


The C standard prohibits a goto into a function scope where a VLA exists.

A VLA and the call to alloca function should have the same result on low level.

(I could be wrong, as I'm just a C, not a low level programmer, but in my imagin that appears to be witty)

So will the following snippet be also undefined behaivng?

int main()
{
    char *p;

    goto label1;

    {
        p = _alloca(1);
label1:
        p = NULL;
    }
}

Ofcourse I cant refference p, but whats about the behaviour?


回答1:


Actually, the rule 6.8.6.1 states:

  A goto statement is not allowed to jump past any declarations of objects 
  with variably modified types.

In your code, there does not exist an object with variably modified types. alloca does not declare an object (that the compiler has to care of). Thus, there is nothing like a scope for alloca, and no reason for undefined behavior in the sense of rule 6.8.6.1.

EDIT

To elaborate the answer a bit: the "undefinedness" of the behavior in case of VLA is due to the promise of a declaration that an object is "known" within its scope (at language level). In general, a declaration sets a context for code execution. There is no need that it is executed at runtime. However, this is not true in case of VLA: here this promise is implemented partly at runtime, breaking C's static declaration approach. To avoid further conflicts that would lead to a dynamic typing system, rule 6.8.6.1 avoids such conflicts.

In contrast, at language level alloca is simply a function; its call does not constitute any scope. It makes only a promise about its run-time behavior in case it is called. If it isn't called, we do not "expect" anything from a function. Thus, its pure existence does not raise any conflict: both cases (bypassing or non-bypassing) have a well defined semantic.




回答2:


A VLA and the call to alloca function should have the same result on low level.

There are still a few differences. A VLA object is discarded when the scope where it is declared ends and the memory object allocated by alloca is discarded when the function returns.

This makes a difference because the requirement in c99, 6.8.6.1p1 ("A goto statement shall not jump from outside the scope of an identifier having a variably modified type to inside the scope of that identifier") is concerned by the runtime allocation / deallocation of objects with variably modified type. Here the alloca statement is not executed after goto is performed, so I would not think the goto call would invoke undefined behavior.




回答3:


The C Standard has nothing to say about the behavior of alloca(). Some compilers use the stack in a very predictable fashion, and access automatic variables using a largely-redundant frame pointer. On such compilers, it's possible to reserve space on the stack by simply subtracting a value from the stack pointer, without the compiler having to know or care about the reservation in question. Such code will break badly, however, if the compiler uses the stack in ways that the application wasn't expecting.

I don't think that something like:

  int *p = 0;
  if (!foo(1,2,3))
    goto skip_alloca;
  p=alloca(46);
skip_alloca:
  bar(4,5,6);
  ...

is apt to be any more dangerous than:

  int *p = 0;
  if (foo(1,2,3))
    p=alloca(46);
  bar(4,5,6);
  ...

If there is no residue on the stack from the function call at the time the alloca() is performed, either operation would likely be safe. If there is residue on the stack at the time of the alloca (e.g. because the compiler opts to defer cleanup of foo's arguments until after the call to bar) that would make alloca() misbehave badly. Using the goto version of the code might actually be safer than the version with if, because it would be harder for a compiler to identify that deferring the cleanup from foo might be advantageous.



来源:https://stackoverflow.com/questions/23823277/is-a-goto-in-allocas-function-scope-valid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!