小编Ami*_*ram的帖子

Helgrind(Valgrind)和OpenMP(C):避免误报?

Valgrind线程错误检测工具Helgrind的文档,可在此处找到

警告说,如果你使用GCC来编译你的OpenMP代码,GCC的OpenMP运行时库(libgomp.so)将导致混乱的数据争用的误报,因为它使用原子机器指令和Linux futex系统调用而不是POSIX pthreads原语.它告诉您,您可以通过使用--disable-linux-futex配置选项重新编译GCC来解决此问题.

所以我尝试了这个.我使用配置选项编译并安装到本地目录(〜/ GCC_Valgrind/gcc_install)一个新的GCC版本4.7.0(撰写本文时的最新版本)--disable-linux-futex.然后我创建了一个没有可见数据竞争的小型OpenMP测试程序(test1.c):

/* test1.c */

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

#define NUM_THREADS 2

int a[NUM_THREADS];

int main(void) {
        int i;
#pragma omp parallel num_threads(NUM_THREADS)
        {
                int tid = omp_get_thread_num();
                a[tid] = tid + 1;
        }
        for (i = 0; i < NUM_THREADS; i++)
                printf("%d ", a[i]);
        printf("\n");
        return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

我编译了这个程序如下

~/GCC_Valgrind/gcc_install/bin/gcc -Wall -fopenmp  -static -L~/GCC_Valgrind/gcc_install/lib64 -L~/GCC_Valgrind/gcc_install/lib -o test1 test1.c
Run Code Online (Sandbox Code Playgroud)

但是,我得到了30个误报数据竞赛报告! …

c valgrind openmp race-condition false-positive

39
推荐指数
1
解决办法
3597
查看次数

如何使用自定义版本的glibc和静态链接构建C程序?

我已经构建了glibc 2.14并将其安装在目录中~/GLIBC/glibc_install.现在我想使用这个C库而不是系统的默认C库来构建和运行程序.

  • 为了确保我使用的是自定义glibc,我添加了一个put glibc/stdio-common/printf.c:__printf来打印消息的调用.

  • 然后我重建并重新安装了glibc.

  • 然后我写了一个"Hello,World"程序并尝试编译并链接如下:

    gcc -nodefaultlibs -static -lgcc -L~/GLIBC/glibc_install/lib -o myprog myprog.c
    
    Run Code Online (Sandbox Code Playgroud)

但是我得到以下链接器错误报告:

/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crt1.o: In function `_start':
(.text+0x19): undefined reference to `__libc_csu_init'
/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crt1.o: In function `_start':
(.text+0x25): undefined reference to `__libc_start_main'
/tmp/ccACTQEp.o: In function `main':
c1.c:(.text+0xa): undefined reference to `puts'
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

c glibc ld static-linking

21
推荐指数
3
解决办法
1万
查看次数

仅为我自己禁用并重新启用地址空间布局随机化

我想在我的系统(Ubuntu Gnu/Linux 2.6.32-41-server)上禁用地址空间布局随机化(ASLR),但是,如果我使用

sysctl -w kernel.randomize_va_space=0
Run Code Online (Sandbox Code Playgroud)

我认为,这种变化会影响系统上的所有用户.(这是真的吗?)我如何限制仅作为用户禁用ASLR对我自己的影响,或者仅限于我调用命令禁用的shell会话?

顺便说一句,我看到我系统的当前(默认)设置是

kernel.randomize_va_space = 2
Run Code Online (Sandbox Code Playgroud)

为什么2而不是1或3?在哪里可以找到有关/ proc/sys设置的数值,范围及其含义的文档?谢谢!

linux bash virtual-address-space aslr sysctl

21
推荐指数
2
解决办法
2万
查看次数

x86_64调用约定和堆栈帧

我试图理解GCC(4.4.3)为在Ubuntu Linux下运行的x86_64机器生成的可执行代码.特别是,我不明白代码如何跟踪堆栈帧.在过去,在32位代码中,我习惯于在几乎每个函数中看到这个"序幕":

push %ebp
movl %esp, %ebp
Run Code Online (Sandbox Code Playgroud)

然后,在功能结束时,也会出现"结局"

sub $xx, %esp   # Where xx is a number based on GCC's accounting.
pop %ebp
ret
Run Code Online (Sandbox Code Playgroud)

或者干脆

leave
ret
Run Code Online (Sandbox Code Playgroud)

这完成了同样的事情:

  • 将堆栈指针设置为当前帧的顶部,就在返回地址的正下方
  • 恢复旧的帧指针值.

在64位代码中,正如我通过objdump反汇编看到的那样,许多函数不遵循这个约定 - 它们不会推送%rbp然后将%rsp保存到%rbp,像GDB这样的调试器如何构建回溯?

我的真正目标是尝试找出一个合理的地址,当执行到达程序中的任意函数的开始时,可​​以将堆栈指针向下移动时作为用户堆栈的顶部(最高地址).例如,对于"top",argv的原始地址是理想的 - 但是我无法从主要调用的任意函数访问它.我一开始以为我可以使用旧的回溯方法:追踪保存的帧指针值,直到保存的值为0 - 然后,下一个可以算作最高实际值.(这与获取argv的地址不同,但它会 - 比如说,找出_start或任何_start调用的堆栈指针值[例如__libc_start_main].)现在,我不知道如何获得64位代码中的等效地址.

谢谢.

c stack x86-64 backtrace calling-convention

13
推荐指数
1
解决办法
7376
查看次数

如何在C代码中获取变量的类型?

有没有什么方法可以通过程序本身的某种机制在C中自动发现变量的类型,或者 - 更有可能 - 通过使用编译器的预编译脚本传递到它的位置解析了变量并为它们分配了类型?我正在寻找关于此的一般性建议.下面是关于我需要什么以及为什么的更多背景.

我想改变OpenMP减少子句的语义.在这一点上,简单地通过调用函数替换源代码中的子句(通过脚本)似乎是最容易的,然后我可以定义函数来实现我想要的缩减语义.例如,我的脚本会转换它

#pragma omp parallel for reduction(+:x)
Run Code Online (Sandbox Code Playgroud)

进入这个:

my_reduction(PLUS, &x, sizeof(x));
#pragma omp parallel for
Run Code Online (Sandbox Code Playgroud)

在哪里,我早些时候(说)

enum reduction_op {PLUS, MINUS, TIMES, AND,
  OR, BIT_AND, BIT_OR, BIT_XOR, /* ... */};
Run Code Online (Sandbox Code Playgroud)

my_reduction签名

void my_reduction(enum reduction_op op, void * var, size_t size);
Run Code Online (Sandbox Code Playgroud)

除其他外,my_reduction必须像程序员最初预期的那样将加法运算应用于约简变量.但我的功能无法知道如何正确地做到这一点.特别是,尽管它知道operation(PLUS)var的类型,原始变量()的位置以及变量类型的大小,但它不知道变量的类型本身.特别是,它不知道是否var具有整数或浮点类型.从低级别POV来看,这两类类型的加法操作完全不同.

如果只有typeofGCC支持的非标准运算符可以像sizeof一样工作 - 返回某种类型的变量 - 我可以轻松地解决这个问题.但是typeof并不像sizeof:它只能在l值声明中使用.

现在,编译器显然在完成生成可执行代码之前就知道了x的类型.这让我想知道我是否可以某种方式利用GCC的解析器,只是获取x类型并将其传递给我的脚本,然后再一次运行GCC来编译我修改过的源代码.那么宣布就足够简单了

enum var_type { INT8, UINT8, INT16, UINT16, /* ,..., */ FLOAT, DOUBLE};
void my_reduction(enum reduction_op op, …
Run Code Online (Sandbox Code Playgroud)

c gcc types typeof openmp

11
推荐指数
3
解决办法
2万
查看次数

mmap on/proc/pid/mem

有没有人成功用Linux内核2.6 mmap'/proc/pid/mem文件?我收到一个ENODEV(没有这样的设备)错误.我的电话看起来像这样:

char * map = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, mem_fd, offset);
Run Code Online (Sandbox Code Playgroud)

我通过在调试时查看/ proc/pid/maps文件进行验证,当执行到达此调用时,offset具有堆栈顶部的值减去PAGE_SIZE.我还用ptrace验证了mmap是将errno设置为ENODEV.

c linux mmap systems-programming procfs

10
推荐指数
1
解决办法
4263
查看次数

带有 subcaption 包的 LaTeX subfloat:缺少数字,视为零

我想制作一个由两个子图组成的图。在阅读了关于subfloats的维基百科子条目,我试图完全遵循它,所以我没有使用subfigorsubfigure包,只使用captionandsubcaption包。不过,我收到一个Missing number, treated as zero错误,指向带有\begin{subfigure}.

我究竟做错了什么?

下面是我的代码:

% In preamble:
\usepackage{url}
\usepackage{graphicx}
\usepackage{caption}
\usepackage{subcaption}
\usepackage{rotating}
\usepackage[table]{xcolor}
\usepackage{multirow}
\usepackage{amsfonts}


% In document:
\begin{figure}[htpb]
\begin{subfigure}[b]{width=0.45\textwidth}
\centering
\includegraphics[width=\textwidth]{img_a}
\end{subfigure}
\begin{subfigure}[b]{width=0.45\textwidth}
\centering
\includegraphics[width=\textwidth]{img_b}
\end{subfigure}
\caption{A caption.}
\label{fig:my-figure}
\end{figure}
Run Code Online (Sandbox Code Playgroud)

latex package figures

5
推荐指数
0
解决办法
7327
查看次数

如何grep包含" - >"的字符串

我在单个目录->foo中的所有*.cpp文件中查找文字字符串.如果我试试

grep -F "->foo" *.cpp
Run Code Online (Sandbox Code Playgroud)

grep报道

Invalid option -- '>'
Run Code Online (Sandbox Code Playgroud)

然后,如果我尝试

grep -F "-\>foo" *.cpp
Run Code Online (Sandbox Code Playgroud)

我明白了

Invalid option -- '\'
Run Code Online (Sandbox Code Playgroud)

我怎样才能使这个工作?

c++ grep

3
推荐指数
2
解决办法
592
查看次数

Fortran 77如何分配公共块变量?

我正在用C开发一个应该使用C,C++或Fortran代码的库.它使用的一种机制是捕获堆栈,堆或数据/ bss段中的页面的写入.在这种情况下,"堆"是库从映射文件创建的特殊堆.我发现我的库未能在Fortran应用程序中捕获对变量的写入.变量声明为

double precision u(5,I,J,K)
Run Code Online (Sandbox Code Playgroud)

其中I,J和K是整数参数(即常数).然后代码将u包含在称为"字段"的公共块中.

在GDB下调试时,我发现u的地址不属于三个数据段中的任何一个.(因此库无法捕获写入!)然后我查看/ proc // maps伪文件,发现u的地址落入系统注释为"堆"的范围内.但你是怎么进入这个"堆"的?在这种情况下,Fortran 77代码不使用非标准的"allocate"关键字在堆上进行分配.有人可以向我解释Fortran 77(在Ubuntu Linux x86-64下)在"堆"上分配的变量,以及首先如何创建这个"堆"?

c heap fortran fortran77 fortran-common-block

2
推荐指数
1
解决办法
1710
查看次数

第一个格式字符串字符不是空格时 scanf 的行为

scanf应该消耗并丢弃格式字符串中不属于转换说明符的任何字符。但当非空白非转换字符出现在格式字符串的前面时,其行为似乎有所不同。为什么?

int main() {
    int num, num2;
    printf("> ");
    while (scanf("> %d %d", &num, &num2)) {
        printf("You entered the number %d %d.\n", num, num2);
        printf("> ");
    }
    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

如果您构建并运行它并输入

int main() {
    int num, num2;
    printf("> ");
    while (scanf("> %d %d", &num, &num2)) {
        printf("You entered the number %d %d.\n", num, num2);
        printf("> ");
    }
    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

在提示符处,它打印消息和重复的提示符,然后立即退出。

因此,这意味着第一次scanf返回,然后在用户可以输入另一组令牌之前返回。如果您从格式字符串中删除,则循环将运行,直到用户输入非数字的内容,然后导致返回- 这是我期望的行为。20> scanf0

另外,如果我在第一个转换说明符之后放置相同的符号,则循环将继续按预期运行。也就是说,如果格式字符串具有,例如,"%d > %d"并且用户输入 …

c scanf format-string

1
推荐指数
1
解决办法
113
查看次数

退出状态代码4479

有没有人碰巧知道退出状态代码4479(0x117f)在Ubuntu Linux系统上意味着什么?我没有我的程序编码它得到这个(我只有EXIT_SUCCESS和EXIT_FAILURE,分别是0和1),我似乎无法找到255以上的代码列表.谢谢!

linux process exit exitstatus

0
推荐指数
1
解决办法
338
查看次数

返回值的简单模板类成员函数特化

我试图调用模板类成员函数特化,从类的构造函数中返回一个值,我似乎无法找到正确的语法(如果它存在).下面是我的代码,下面是编译器(不是链接器)的错误消息.

#include <iostream>

class A {};

class B {};

template <typename T>
class C
{
    public:
        C()
        {
            std::cout << "C constructed." << std::endl;
            std::cout << name() << std::endl;;
        }
        template constexpr const char * name();
};

template <> const char * C<A>::name() { return "You got an A."; }
template <> const char * C<B>::name() { return "You got a B."; }


int main()
{
    C<A> c_a;
    C<B> c_b;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

错误消息:g ++ -std = c ++ 11 …

c++ templates template-specialization c++11

0
推荐指数
1
解决办法
80
查看次数

Two's Complement Division Algorithm (Intel)

On Intel machines, integer division requires a sequence of two instructions:

\n
    \n
  1. After you store the dividend in the a register (e.g., %eax), you extend the sign of the dividend into the corresponding d register (%edx).
  2. \n
  3. The idiv or div instruction itself then performs the division and places the quotient in the a register and the remainder in the d register.\nBut why does the operation require the sign extension? What does the algorithm actually do …

x86 assembly cpu-architecture division twos-complement

0
推荐指数
1
解决办法
336
查看次数