gpt4 book ai didi

c++ - basename freebsd 与 std::string 一起工作正确,但没有 not

转载 作者:搜寻专家 更新时间:2023-10-31 01:16:31 25 4
gpt4 key购买 nike

我要小程序

首先

// compile with -lpthread
// TEST:
// basename


#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <libgen.h>
#include <limits.h>
#include <inttypes.h>


// DATASET_LEN
#ifndef DATASET_LEN
#define DATASET_LEN 10000
#endif
// THREADS_NUM
#ifndef THREADS_NUM
#define THREADS_NUM 16
#endif


// need to call free(3) after
char** generateArray() {
char** dataset = (char**)malloc(sizeof(char*) * DATASET_LEN);
// fill dataset
for (size_t i = 0; i < DATASET_LEN; ++i) {
dataset[i] = (char*)malloc(sizeof(char) * CHAR_MAX);
sprintf(dataset[i], "%i/%i/", rand(), rand());
}

return dataset;
}

// pthread_create(3) callback
void* run(void* args) {
char** dataset = generateArray();
char* baseName;

for (size_t i = 0; i < DATASET_LEN; ++i) {
baseName = basename(dataset[i]);
printf("%s\n", baseName);

free(dataset[i]);
}

free(dataset);
}

// main
int main(int argc, char** argv) {
pthread_t* threads = (pthread_t*)malloc(sizeof(pthread_t) * THREADS_NUM);
// threads start
for (int i = 1; i <= THREADS_NUM; ++i) {
pthread_create(&threads[i-1], NULL, run, NULL);
fprintf(stderr, "Thread %u started\n", i);
}
// threads join
for (int i = 1; i <= THREADS_NUM; ++i) {
pthread_join(threads[i-1], NULL);
fprintf(stderr, "Thread %u finished\n", i);
}
free(threads);

return EXIT_SUCCESS;
}

第二个:

// compile with -lpthread
// TEST:
// basename


#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <libgen.h>
#include <limits.h>
#include <inttypes.h>
#include <string>


// DATASET_LEN
#ifndef DATASET_LEN
#define DATASET_LEN 10000
#endif
// THREADS_NUM
#ifndef THREADS_NUM
#define THREADS_NUM 16
#endif


// need to call free(3) after
char** generateArray() {
char** dataset = (char**)malloc(sizeof(char*) * DATASET_LEN);
// fill dataset
for (size_t i = 0; i < DATASET_LEN; ++i) {
dataset[i] = (char*)malloc(sizeof(char) * CHAR_MAX);
sprintf(dataset[i], "%i/%i/", rand(), rand());
}

return dataset;
}

// pthread_create(3) callback
void* run(void* args) {
char** dataset = generateArray();
char* baseName;
std::string tmpStr;

for (size_t i = 0; i < DATASET_LEN; ++i) {
baseName = basename(dataset[i]);
tmpStr = std::string(baseName);
printf("%s\n", tmpStr.c_str());

free(dataset[i]);
}

free(dataset);
}

// main
int main(int argc, char** argv) {
pthread_t* threads = (pthread_t*)malloc(sizeof(pthread_t) * THREADS_NUM);
// threads start
for (int i = 1; i <= THREADS_NUM; ++i) {
pthread_create(&threads[i-1], NULL, run, NULL);
fprintf(stderr, "Thread %u started\n", i);
}
// threads join
for (int i = 1; i <= THREADS_NUM; ++i) {
pthread_join(threads[i-1], NULL);
fprintf(stderr, "Thread %u finished\n", i);
}
free(threads);

return EXIT_SUCCESS;
}

这两个程序,在 linux 上工作正常,但首先在 freebsd 上(没有 std::string)不工作
谁能解释一下为什么?

我在 /usr/src/lib/libc/gen/basename.c 看到 freebsd src 并且在函数中看到一个静态变量。
但正因为如此,std::string 程序也一定不能正常工作

正常情况下,我的意思是,它只输出数字和新行

对于我使用的测试:./freebsd-threaded-basename | egrep -av '^[0-9\n\s]+$' | env LANG=c less

UPD 我尝试使用 strdup() 或 strcpy() 结果是一样的——不正常
UPD *每次* 带有 std::string 的版本运行时都按预期工作

最佳答案

您的程序行为不可预测的原因是 basename,它不是线程安全的。 basename 有点过时了。现代 C++ 应用程序倾向于使用其他方式来解析文件路径。 Boost 文件系统库很流行,可以用来做这件事。

如果你坚持使用basename,把它和一些能得到basename结果的代码一起放到临界区(比如printf,或 strcpy,或其他)。这保证了 basename 的结果不会同时从多个线程访问。这意味着正确的行为。

现在对“为什么”进行一些猜测。 (只是猜测,因为无法预测非线程安全的多线程程序究竟是如何工作的)。

程序的第一个版本执行部分并行的 basename 循环(basename 函数和循环本身),部分顺序执行(printffree 是线程安全函数,它们的实现受临界区保护。

第二个版本添加了 std::string,这意味着更多的顺序代码。它为新字符串分配内存,释放旧内存(这两个操作都是线程安全的并受临界区保护)。此外(在某些实现中)使用原子操作来更新共享计数器,这也会降低并行度。所有这些实际上将您的程序从并行转换为完全顺序。所有线程大多都在等待一些互斥量。或者有时执行一些复杂的 printf/memory/std::string 计算。并且很少有线程之一进行相对简单的 basename 计算。几乎就像您在 basename 周围添加了一个关键部分。

Linux 测试的正确结果可能是因为 printffree 足以使程序在这种情况下几乎是连续的。 (因为某些事情在 Linux 中或由于不同的硬件而有所不同)。

关于c++ - basename freebsd 与 std::string 一起工作正确,但没有 not,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9061119/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com