return a lambda capturing function parameter reference - c++11

#include <iostream>
#include <functional>
using namespace std;
std::function<void(void)> makeLambda(int param)
{
return [&param](){cout << param << endl;};
}
int main()
{
auto callback = makeLambda(5);
callback();
}
Based on lambda description as following, it looks the program will cause an undefined behavior because when callback is invoked, the captured var, function parameter, is out-of-scope. But I see it always can print 5.
My g++ version is gcc-4.9.1.
Dangling references
If an entity is captured by reference, implicitly or explicitly, and
the function call operator of the closure object is invoked after the
entity's lifetime has ended, undefined behavior occurs. The C++
closures do not extend the lifetimes of the captured references.
Same applies to the lifetime of the object pointed to by the captured
this pointer.
Why can it work?

As you note, this is undefined behaviour. Anything can happen, including appearing to work. If you switch compiler, change flags, forget to do the dishes, or get up an hour later, you could get completely different results.
As an example, Clang prints 32767 for some version and set of flags.

Related

How to make GCC enforce pure/const attribute?

I tried using attribute const and pure to try to make GCC enforce that a function is not allowed to access any global variables but this compiles just fine:
#include <stdlib.h>
#include <stdio.h>
int data;
__attribute__((const))
int test_func(int val){
data = val;
return data;
}
int main(){
scanf("%d", &data);
printf("test: %d\n", test_func(data));
return 0;
}
This should not compile.
Is there a way to enforce the rule that neither the function itself nor any other functions it calls can access any variables besides their arguments?
GCC manual says that __attribute__((const)) is used by the programmer to indicate the behavior of the function so that it can be optimized better.
Calls to functions whose return value is not affected by changes to the observable state of the program and that have no observable effects on such state other than to return a value may lend themselves to optimizations such as common subexpression elimination. Declaring such functions with the const attribute allows GCC to avoid emitting some calls in repeated invocations of the function with the same argument values.
In the documentation there are some cases for which a compile error is promised, and wrong behavior (accessing globals within the function) is not one of those. Therefore you are responsible to not use this attribute for functions that use globals.

Universal Reference and Named Parameter Ideom

I wrote this code and compile with gcc.
I expected to get result "2", but result was "0".
Other compiler clang and vc prints "2".
Is it undefined behaviour or not?
#include <stdio.h>
struct Test {
Test& inc() {
++value;
return *this;
}
int value = 1;
};
int main() {
auto&& t = Test().inc(); // The life-time of the temporary might extended.
printf("%d\n", t.value); // gcc prints "0". dangling reference?
return 0;
}
c.f. build reslut on http://rextester.com
gcc result
clang result
vc result
The forwarding reference (that's what universal references have been renamed to) is irrelevant -- you would observe the same behaviour with a regular reference.
The issue is that the Test's lifetime is not extended, because it is not directly bound to the reference, as auto &&t = Test(); would be. Instead, its member function returns an lvalue reference, which is used to deduce and initialize t as a Test & (you can check this via decltype(t)). Then the temporary is destructed, the reference is now dangling, and using it is undefined behaviour.

std::function still requires parameters when no place holders are coded in

I wanted to know what I might be doing wrong here. This is my code sample. Its just a rough code sample depicting the use of function pointers.In the following example the fuunction pointer takes in a parameter.However that parameter was already assigned during function pointer assignment.Now in order to invoke the function pointer i still need to provide a parameter value although that value is nver used (unless i used std::placeholder). My question is how do i invoke a function pointer that requires a parameter and whose parameter has already been assigned without passing in a parameter.
#include <iostream>
#include <functional>
using namespace std;
std::function<std::string(std::string)> fptr;
std::string foo()
{
return fptr(); //--->statement A - I need to invoke this funct ptr without passing a parameter as a parameter has already been assigned in statement B
}
std::string bar(std::string p)
{
return p;
}
int main()
{
fptr = std::bind(&bar,"Hello"); --->statement B
std::cout << foo();
}
Notice in std::bind I did not use any placeholders and "Hello" is the parameter to the function bar. My question is why does
return fptr();
not work. If i do the following
return fptr("Bye");
It works and returns "Hello" . (No point of passing parameter during fptr call) Why does it not work without a parameter ?
The result of std::bind allows you passing more arguments than it needed, and ignore these extra arguments. In your case, std::bind(&bar, "Hello") can be called without arguments, or, declared by fptr, with one std::string argument.
The solution to your problem is easy, just change the type of fptr to std::function<std::string()>, which accept no arguments and return a string.

FILE pointer acts different as a function parameter in C

In the following code I created a char pointer and a FILE pointer, and tried to pass both to a function "by value of course".
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void move(char *s){
++s;
}
void moveF(FILE *f){
getc(f);
}
int main(){
char *s = malloc(64);
strcpy(s,"123456");
puts(s);
move(s);
puts(s);
//~~~~~~~~~~
FILE *f = fopen("file1","r");
printf("%d\n",(int)ftell(f));
moveF(f);
printf("%d\n",(int)ftell(f));
}
I know that passing by value means that the parameter is a copy of the original variable in the calling function, That's why you can notice that after passing the char pointer, it's value in main function was not changed at all, but what is weird is that passing a FILE pointer and changing the value of the parameter caused changing the value of the variable inside main function.
Can someone please explain this behavior.
Thanks.
Passing a pointer to an object is the same as passing the object by reference. Hence, you’re passing a FILE structure by reference. The pointers in either function point to the same object in memory, so either can modify the object and see the others changes.

Clang does not allow static_cast to parent class with template, while g++ and icc allow

I am trying my C++11 code to see if all recent major compiler supports the features I used, and the following shortened code
#include <valarray>
struct T
{
double vv[3];
};
class V : public std::valarray<T>
{
public:
auto begin()->decltype(std::begin(static_cast<std::valarray<T>>(*this)))
{
return std::begin(static_cast<std::valarray<T>>(*this));
}
};
int main(void)
{
}
would compile with g++ 4.8.1(from Debian sid repository), Intel C++ compiler 13.1.1 20130313, but not Clang 3.3-2(from Debian sid repository).
The given error is:
test.cpp:11:73: error: no viable conversion from 'V' to 'std::valarray<T>'
auto begin()->decltype(std::begin(static_cast<std::valarray<T>>(*this)))
^~~~~
However, code like this
namespace std
{
auto begin(V& vv) -> decltype(std::begin(static_cast<V::parent_t>(vv)))
{
return std::begin(static_cast<V::parent_t>(vv));
}
}
would compile by all three compilers.
My question is: is the code itself allowed by the language standard, just Clang miscompiled it, or it is only supported by g++/icc extension? Or it is undefined behavior?
The code very dangerous and needs to be fixed even for GCC and ICC.
You're doing a static_cast to a value type, not a reference or pointer. That creates a new temporary valarray object, so the const overload of begin gets called (probably not what you intended), and the iterator returned by begin() refers to the temporary which goes out of scope immediately, so the returned iterator is invalid and dereferencing it is undefined behaviour.
The code will compile like this:
auto begin()->decltype(std::begin(std::declval<std::valarray<T>&>()))
{
return std::begin(static_cast<std::valarray<T>&>(*this));
/* cast to reference type! ^^^^^^^^^^^^^^^^^ */
}
The decltype doesn't need to cast this, it just needs to know the type of calling std::begin on a valarray<T>, so it doesn't matter if the type is incomplete because you don't need a cast.
In the body of the function the type is considered complete anyway, so the cast is valid.

Resources