开发者社区 > 云存储 > 对象存储OSS > 正文

【OSS 新版C++ SDK BUG】C++使用阿里云OSS SDK时,遍历OSS上的文件时崩溃

最新版的C++SDK我是在阿里云文档页面下载的。
2023-10-20号下载的当时的版本是1.9.0,现在去下也是1.9.0
但是github上,我今天看了,版本是1.9.1,最后更新时间是8月的时候。真的很迷。
看了一下更新内容,貌似也没涉及到这个。以下是他的更新内容.

fix bugs in resumable resumable upload/download.
fix conversion issue caused by locale
add CURLE_SEND_FAIL_REWIND into retryable error.
support to unencode slash in presigned url path.
The file may uploaded incompletely in unplug & plug hard disk test.
GetBukcetStatResult returns more information.
support list buckets by region.
compatible with OpenSSL 3.0.
add EnvironmentVariableCredentialsProvider.
support path style.
add RestoreInfo filed in ListObjects/ListObjectsV2 result.

暂时没时间折腾这个了。因为下载我们这边使用的是CDN所以影响不大。但还是反映一下,避免后来者踩坑里。如果真的是版本问题,看到的小伙伴如果试了1.9.1是没有问题的,记得Call一声。我们有空也升级一下。

----------以下是10月30日的内容-----------
在使用C++SDK遍历文件时,出现BUG
下图是我的OSS上的根下的文件
22.png
使用是的RAM来操作的,生成临时的STS确定是没有问题的,因为生成的STS用于上传和获取单个文件信息都是正常且没有问题的。就是遍历文件会崩溃.
下图是关键代码
11.png
上面代码中红框部分,在遍历文件时,打印输出结果如下图
33.png
可以看到绿色箭头第一次打印输出a.jpg时,是正常的,OSS上确时有这个文件,但是在第二次打印输出时"0A966B546273DF37D3CE9F9599037616"这是什么玩意,OSS上根本没这个文件,之后的遍历就开始出错,然后就崩溃了。
如果是用于老版的C++SDK是正常没有问题的。现在使用的是新版的SDK出问题了。根据结果来推测,就应该是BUG。

----------以下是10月28日前的内容-----------
环境:windows10 64位。QT5.15.2
说明,这段代码是自己之前确定没有问题,然后弄成一个函数方便自己使用的。
访问的是方式是使用ram生成临时的STS来操作。
用的最新的SDK
上传文件到oss上没有问题。
获取oss上单个文件信息没有问题。
判断oss上是否存在指定文件也没有问题
以上这些都是通过OSS的SDK实现的
因为是要遍历文件所以RAM中也已经添加了oss:ListObjects和"oss:GetObject"相应的权限都已开放

现在遇到一个问题,在C++QT中使用阿里云OSS的C++SDK进行操作OSS时。程序就崩溃了。下面是遍历代码

std::string nextMarker = "";
    bool isTruncated = false;
    do {
        /* 列举文件。*/
        ListObjectsRequest request(bucketName);
        /* 设置列举文件的最大个数为500。*/
        request.setMaxKeys(500);
        request.setPrefix(ossDirPath.toStdString());
        request.setMarker(nextMarker);
        auto outcome = client->ListObjects(request);
        // outcome.isSuccess()值为true
        if (!outcome.isSuccess()) return false;


        for (const auto& object : outcome.result().ObjectSummarys()) {
            std::cout << "object"<<",name:" << object.Key() <<",size:" << object.Size() <<",lastmodify time:" << object.LastModified() << std::endl;
            std::string ossFilePathName = object.Key();
            std::cout << ossFilePathName;
        }
        nextMarker = outcome.result().NextMarker();
        isTruncated = outcome.result().IsTruncated();
        std::cout<<isTruncated;
    } while (isTruncated);

代码我已经精简了,其它那些确定百分之百无关的代码,都已经去掉。剩下的就是上面的代码了。
我在oss上有一个目录叫ddd,在ddd目录之下有子目录和文件。而上面的代码,运行之后,会在for循环里面打印出来一个文件。之后就崩溃的图片
34.jpg

于是我再次把代码精减


std::string nextMarker = "";
    bool isTruncated = false;
    do {
        /* 列举文件。*/
        ListObjectsRequest request(bucketName);
        /* 设置列举文件的最大个数为500。*/
        request.setMaxKeys(500);
        request.setPrefix(ossDirPath.toStdString());
        request.setMarker(nextMarker);
        auto outcome = client->ListObjects(request);

        // outcome.isSuccess()值为true
        if (!outcome.isSuccess()) return false;

        nextMarker = outcome.result().NextMarker();
        isTruncated = outcome.result().IsTruncated();
        std::cout<<isTruncated;
    } while (isTruncated);

依然崩溃,只是没有上一次的弹出提示而已了,是直接崩溃

再次精减代码

std::string nextMarker = "";
    bool isTruncated = false;
    do {
        /* 列举文件。*/
        ListObjectsRequest request(bucketName);
        /* 设置列举文件的最大个数为500。*/
        request.setMaxKeys(500);
        request.setPrefix(ossDirPath.toStdString());
        request.setMarker(nextMarker);
        auto outcome = client->ListObjects(request);
    } while (isTruncated);

依然无提示直接崩溃。

断点调试到这一句auto outcome = client->ListObjects(request);不会进入到while就直接崩溃了
client是百分之百实例化了的,不然上传和查看文件这些操作肯定都会报错

// 初始化OSS网络
    InitializeSdk();
    client = new OssClient(endpoint, accessKeyId, accessKeySecret, securityToken, conf);

所以现在不知道是什么问题了。有大佬能给出个提示什么的吗?

额外再问个其它的问题
SDK中例子有这代码

/* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();

这个EnvironmentVariableCredentialsProvider是什么意思,一直说从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。这个环境变量在哪里配置?找到与EnvironmentVariableCredentialsProvider相关的信息也不明白他说的“请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。”

卡在这里面了

展开
收起
楼顶晒月光 2023-10-28 16:13:46 419 1
3 条回答
写回答
取消 提交回答
  • 从你提供的截图来看,似乎是在遍历OSS上的文件时出现了问题。这可能是因为OSS C++ SDK的一个bug导致的。我建议你尝试以下几种解决方法:

    1. 更新到最新版本的OSS C++ SDK。如果你已经在使用最新版本,那么可以尝试回退到一个之前的版本,看看问题是否得到解决。

    2. 检查你的代码,确保你没有在处理文件时出现错误。例如,确保你在遍历文件时使用了一个有效的prefix参数,并且你已经正确设置了maxKeys和marker参数。

    3. 如果你无法确定问题的原因,你可以尝试使用阿里云的OSS控制台来手动列出OSS上的文件。这样可以帮助你更好地理解问题出在哪里。

    2023-10-30 16:01:37
    赞同 3 展开评论 打赏
  • 北京阿里云ACE会长

    可以尝试在循环中添加一些调试语句,以确定在哪个对象上出现了问题。
    另外,根据阿里云OSS官方文档,当使用RAM临时授权访问OSS时,每个请求都需要携带RAM授权的临时访问凭证(STS Token)。可以检查代码中设置STS Token的逻辑是否正确,以及是否在遍历对象时正确地传递了STS Token。
    关于 EnvironmentVariableCredentialsProvider,这是一个从环境变量中获取访问凭证的类。在使用这个类之前,需要确保环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET已经设置。这些环境变量通常是在操作系统级别设置的,可以在操作系统的环境变量设置中进行配置。例如,在Windows系统中,可以右键点击“计算机”图标,选择“属性”>“高级系统设置”>“环境变量”,在“系统变量”下找到“OSS_ACCESS_KEY_ID”和“OSS_ACCESS_KEY_SECRET”并设置它们的值。

    2023-10-29 08:26:06
    赞同 展开评论 打赏
  • 从你的描述来看,问题可能出在环境变量的设置上。请按照以下步骤检查和设置环境变量:

    1. 确保已经安装了阿里云OSS SDK。如果没有安装,可以参考官方文档进行安装:https://help.aliyun.com/document_detail/32025.html

    2. 设置环境变量。在Windows系统中,右键点击“计算机”或“此电脑”,选择“属性”,然后点击“高级系统设置”。在“系统属性”窗口中,点击“环境变量”按钮。在“系统变量”区域找到名为“OSS_ACCESS_KEY_ID”和“OSS_ACCESS_KEY_SECRET”的变量,如果不存在,请点击“新建”按钮创建。将这两个变量的值分别设置为你的阿里云AccessKey ID和AccessKey Secret。

    3. 重启你的程序,再次运行遍历代码。如果问题仍然存在,请检查其他部分的代码是否有误。

    2023-10-28 20:37:06
    赞同 展开评论 打赏

对象存储 OSS 是一款安全、稳定、高性价比、高性能的云存储服务,可以帮助各行业的客户在互联网应用、大数据分析、机器学习、数据归档等各种使用场景存储任意数量的数据,以及进行任意位置的访问,同时通过丰富的数据处理能力更便捷地使用数据。

相关产品

  • 对象存储
  • 热门讨论

    热门文章

    相关电子书

    更多
    一个跨平台的云服务SDK需要什么 立即下载
    使用C++11开发PHP7扩展 立即下载
    GPON Class C++ SFP O;T Transce 立即下载