Switch "Transfer of Control Bypasses Initialization Of:" When Calling a Function

switch transfer of control bypasses initialization of: when calling a function

section 6.6.4 of the C++ standard:

The goto statement unconditionally
transfers control to the statement
labeled by the identifier. The
identifier shall be a label (6.1)
located in the current function.

section 6.7 of the C++ standard:

It is possible to transfer into a
block, but not in a way that bypasses
declarations with initialization
. A
program that jumps from a point
where a local variable with automatic
storage duration is not in scope to a
point where it is in scope is
ill-formed unless the variable has POD
type (3.9) and is declared without an
initializer

Emphasis added by me. Since switch is really goto in disguise, you're encountering this behavior. To solve this, add braces if you must use a switch

switch (retrycancel)
{
case 4:
{
const std::vector<MainHandles::window_data> windows(
MainHandles().enum_windows().get_results()
);
break;
}
case 2:
//code
}

or refactor into if/else

if (retrycancel == 4) {
const std::vector<MainHandles::window_data> windows(
MainHandles().enum_windows().get_results()
);
} else if (retrycancel == 2)
// code
} else {
...
}

Though it's not obvious to me what you're hoping to accomplish with creating the windows vector inside a switch, so you may want to rethink your design. Note I added a const qualifier to windows since it's not modified in your example.

CUDA : error: transfer of control bypasses initialization of when creating thrust::device_ptr

Some people might tell you that the use of goto in C/C++ isn't a great idea. But to avoid arguments, and allow you to keep the same code structure, you can declare your thrust device pointer at the top of your program (before any goto statements) and then set the pointer value when you are ready to use it, like this:

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <stdio.h>

#include <time.h>

#include <device_functions.h>

int main()
{
const int size = 32;
unsigned int * dev_ips_range_end;
unsigned int * ips_range_end = new unsigned int[size];
for (int i = 0; i < size; i++)
ips_range_end[i] = i;

thrust::device_ptr<unsigned int> dev_ips_range_end_ptr;
cudaError_t cudaStatus;
cudaStatus = cudaSetDevice(0);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaSetDevice failed! Do you have a CUDA-capable GPU installed?");
goto Error;
}
cudaStatus = cudaMalloc((void**)&dev_ips_range_end, size * sizeof(int));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "Problem !");
goto Error;
}

// Copy input vectors from host memory to GPU buffers.
cudaStatus = cudaMemcpy(dev_ips_range_end, ips_range_end, size * sizeof(unsigned char), cudaMemcpyHostToDevice);
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "Problem !");
goto Error;
}

dev_ips_range_end_ptr = thrust::device_pointer_cast(dev_ips_range_end);
thrust::inclusive_scan(dev_ips_range_end_ptr, dev_ips_range_end_ptr + size, dev_ips_range_end_ptr);
return 0;

Error:
cudaFree(dev_ips_range_end);
}

Error: Jump to case label in switch statement

The problem is that variables declared in one case are still visible in the subsequent cases unless an explicit { } block is used, but they will not be initialized because the initialization code belongs to another case.

In the following code, if foo equals 1, everything is ok, but if it equals 2, we'll accidentally use the i variable which does exist but probably contains garbage.

switch(foo) {
case 1:
int i = 42; // i exists all the way to the end of the switch
dostuff(i);
break;
case 2:
dostuff(i*2); // i is *also* in scope here, but is not initialized!
}

Wrapping the case in an explicit block solves the problem:

switch(foo) {
case 1:
{
int i = 42; // i only exists within the { }
dostuff(i);
break;
}
case 2:
dostuff(123); // Now you cannot use i accidentally
}

Edit

To further elaborate, switch statements are just a particularly fancy kind of a goto. Here's an analoguous piece of code exhibiting the same issue but using a goto instead of a switch:

int main() {
if(rand() % 2) // Toss a coin
goto end;

int i = 42;

end:
// We either skipped the declaration of i or not,
// but either way the variable i exists here, because
// variable scopes are resolved at compile time.
// Whether the *initialization* code was run, though,
// depends on whether rand returned 0 or 1.
std::cout << i;
}

Python - Activate conda env through shell script

The error message is rather helpful - it's telling you that conda is not properly set up from within the subshell that your script is running in. To be able to use conda within a script, you will need to (as the error message says) run conda init bash (or whatever your shell is) first. The behaviour of conda and how it's set up depends on your conda version, but the reason for the version 4.4+ behaviour is that conda is dependent on certain environment variables that are normally set up by the conda shell itself. Most importantly, this changelog entry explains why your conda activate and deactivate commands no longer behave as you expect in versions 4.4 and above.

For more discussion of this, see the official conda issue on GitHub.


Edit: Some more research tells me that the conda init function mentioned in the error message is actually a new v4.6.0 feature that allows a quick environment setup so that you can use conda activate instead of the old source activate. However, the reason why this works is that it adds/changes several environment variables of your current shell and also makes changes to your RC file (e.g.: .bashrc), and RC file changes are never picked up in the current shell - only in newly created shells. (Unless of course you source .bashrc again). In fact, conda init --help says as much:

IMPORTANT: After running conda init, most shells will need to be closed and restarted for changes to take effect

However, you've clearly already run conda init, because you are able to use conda activate interactively. In fact, if you open up your .bashrc, you should be able to see a few lines added by conda teaching your shell where to look for conda commands. The problem with your script, though, lies in the fact that the .bashrc is not sourced by the subshell that runs shell scripts (see this answer for more info). This means that even though your non-login interactive shell sees the conda commands, your non-interactive script subshells won't - no matter how many times you call conda init.

This leads to a conjecture (I don't have conda on Linux myself, so I can't test it) that by running your script like so:

bash -i shell_script.sh

you should see conda activate work correctly. Why? -i is a bash flag that tells the shell you're starting to run in interactive mode, which means it will automatically source your .bashrc. This should be enough to enable you to use conda within your script as if you were using it normally.

Why can't variables be declared in a switch statement?

Case statements are only labels. This means the compiler will interpret this as a jump directly to the label. In C++, the problem here is one of scope. Your curly brackets define the scope as everything inside the switch statement. This means that you are left with a scope where a jump will be performed further into the code skipping the initialization.

The correct way to handle this is to define a scope specific to that case statement and define your variable within it:

switch (val)
{
case VAL:
{
// This will work
int newVal = 42;
break;
}
case ANOTHER_VAL:
...
break;
}


Related Topics



Leave a reply



Submit