前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >C++ 中文周刊 2025-02-01 第177期

C++ 中文周刊 2025-02-01 第177期

作者头像
王很水
发布2025-02-04 15:39:12
发布2025-02-04 15:39:12
3200
代码可运行
举报
运行总次数:0
代码可运行

文章

C++26: attributes in structured bindings

结构化绑定的参数可以标记属性attr,比如

代码语言:javascript
代码运行次数:0
复制
std::map<int, std::string> m{
        {1, "one"}, {2, "two"} {3, "three"}};

for(const auto& [ [[maybe_unused]] k, v]: m) {
        DEBUG(k) // only used in debug builds
    std::cout << v << '\n';
}

A pattern for obtaining a single value while holding a lock

通过返回值复制,而不是手动赋值。规避潜在的多余构造

代码语言:javascript
代码运行次数:0
复制
std::mutex m_mutex;
Widget m_widget;

// Get a copy of the widget
Widget widget;
{
    auto guard = std::lock_guard(m_mutex);
    widget = m_widget;
}

这是常规写法,不好。倾向于通过返回值一次赋值

代码语言:javascript
代码运行次数:0
复制
// Get a copy of the widget
Widget widget = [&] {
    auto guard = std::lock_guard(m_mutex);
    return m_widget;
}();

这种lambda用的多了你也可以通过封装函数来返回

代码语言:javascript
代码运行次数:0
复制
Widget CopySavedWidget()
{
    auto guard = std::lock_guard(m_mutex);
    return m_widget;
}

类似的保存-销毁需求

代码语言:javascript
代码运行次数:0
复制
Widget widget = [&] {
    auto guard = std::lock_guard(m_mutex);
    return std::exchange(m_widget, {});
}();

也可以这样封装,更泛化一点

代码语言:javascript
代码运行次数:0
复制
template<typename T>
Widget ExchangeSavedWidget(T&& value)
{
    auto guard = std::lock_guard(m_mutex);
    return std::exchange(m_widget, std::forward<T>(value)):
}

PPSSPP or psp? Uncovering bugs from the past

鉴赏几个PPSSPP项目的bug

代码语言:javascript
代码运行次数:0
复制
static int sceNetAdhocctlGetAddrByName(const char *nickName,
                                       u32 sizeAddr, u32 bufAddr)
{
  ....
// Copied to null-terminated var to prevent unexpected behaviour on Logs
memcpy(nckName, nickName, ADHOCCTL_NICKNAME_LEN); 

  ....
if (netAdhocctlInited)
  {
    // Valid Arguments
    if (nickName != NULL && buflen != NULL)
    {
      ....
    }
    ....
  }
}

如果if里的nickName存在等于nullptr的可能,那么memcpy的行为会有UB,那么这个代码必然有问题了

代码语言:javascript
代码运行次数:0
复制
int internal_profiler_find_cat(const char *category_name, bool create_missing)
{
int i;
for (i = 0; i < MAX_CATEGORIES; i++)
  {
    constchar *catname = categories[i].name;
    if (!catname)
      break;
#ifdef UNIFIED_CONST_STR
    if (catname == category_name)
    {
#else
    if (!strcmp(catname, category_name))                          // <=
    {
#endif
      return i;
    }
  }

if (i < MAX_CATEGORIES && category_name && create_missing)      // <=
  {
    ....
  }     
}

没有检查category_name是不是nullptr就放到strcmp里,潜在bug

代码语言:javascript
代码运行次数:0
复制
static void __GameModeNotify(u64 userdata, int cyclesLate)
{
  ....
if (gameModeSocket < 0)
  {
    // ReSchedule
    CoreTiming::ScheduleEvent(usToCycles(GAMEMODE_UPDATE_INTERVAL) - cyclesLate,
                              gameModeNotifyEvent, userdata);
    return;
  }

auto sock = adhocSockets[gameModeSocket - 1];
  ....
}

数组索引可能是-1

代码语言:javascript
代码运行次数:0
复制
SoftGPU::SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
  : GPUCommon(gfxCtx, draw)
{
  ....
  drawEngine_ = new SoftwareDrawEngine();
  if (!drawEngine_)
    return;
  ....
}

这个指针检查屁用没有,new不出来会抛异常。如果在意就用catch兜住啊

代码语言:javascript
代码运行次数:0
复制
static std::vector<MicWaitInfo> waitingThreads;
....
staticvoid __MicBlockingResume(u64 userdata, int cyclesLate)
{
  ....
int count = 0;
for (auto waitingThread : waitingThreads)
  {
    if (waitingThread.threadID == threadID)
    {
      ....
      if (Microphone::isHaveDevice())
      {
        if (Microphone::getReadMicDataLength() >= waitingThread.needSize)
        {
          ....
          waitingThreads.erase(waitingThreads.begin() + count);    // <=
        }
        else
        {
          ....
        }
      } 
      else
      {
        ....
        waitingThreads.erase(waitingThreads.begin() + count);      // <=
        readMicDataLength += waitingThread.needSize;
      }
    }

    ++count;
  }
}

经典问题,循环中删除

代码语言:javascript
代码运行次数:0
复制
void Int_VecDo3(MIPSOpcode op)
{
  ....
  u32 lastsat = (currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] & 3) << (n + n - 2);
  ....
}

n + n -2可能是负数 <<就UB了

代码语言:javascript
代码运行次数:0
复制
inline float Float16ToFloat(float16 ix)
{
    float x;
    memcpy(&x, &ix, sizeof(float));
    return x;
}

复制越界

代码语言:javascript
代码运行次数:0
复制
void Jit::Comp_SVQ(MIPSOpcode op)
{
  CONDITIONAL_DISABLE(LSU_VFPU);

int imm = (signed short)(op&0xFFFC);
int vt = (((op >> 16) & 0x1f)) | ((op&1) << 5);
  MIPSGPReg rs = _RS;

  CheckMemoryBreakpoint(0, rs, imm);

switch (op >> 26)
  {
    case53: //lvl.q/lvr.q
    {
      if (!g_Config.bFastMemory)
      {
        DISABLE;
      }

      DISABLE;
  ....
}

代码语义重复 DISABLE无论如何都能走到

代码语言:javascript
代码运行次数:0
复制
void BlockAllocator::Block::DoState(PointerWrap &p)
{
  char tag[32];  
....
  size_t tagLen = strlen(tag);
  if (tagLen != sizeof(tag))
    memset(tag + tagLen, 0, sizeof(tag) - tagLen);
  DoArray(p, tag, sizeof(tag));
}

多余的if分支,永远true

代码语言:javascript
代码运行次数:0
复制
void netAdhocValidateLoopMemory()
{
  // Allocate Memory if it wasn't valid/allocated
  // after loaded from old SaveState
  if (   !dummyThreadHackAddr
      || (   dummyThreadHackAddr
          && strcmp("dummythreadhack",
                    kernelMemory.GetBlockTag(dummyThreadHackAddr)) != 0))
  {
  ....
}

条件重复

代码语言:javascript
代码运行次数:0
复制
void QueueCallback(void (*func)(VulkanContext *vulkan, void *userdata),
                   void *userdata)
{ 
  callbacks_.push_back(Callback(func, userdata));
}
void VulkanRenderManager::EndCurRenderStep()
{
for (VKRGraphicsPipeline *pipeline : pipelinesToCheck_)
  {
    if (!pipeline)
    {
      // Not good, but let's try not to crash.
      continue;
    }

    if (!pipeline->pipeline[(size_t)rpType])
    {
      pipeline->pipeline[(size_t)rpType] = Promise<VkPipeline>::CreateEmpty();
      _assert_(renderPass);
      compileQueue_.push_back(CompileQueueEntry(pipeline,
            renderPass->Get(vulkan_, rpType, sampleCount),rpType, sampleCount));
      needsCompile = true;
    }
  }
}

push_back不如emplace_back

C stdlib isn’t threadsafe and even safe Rust didn’t save us

省流 setenv/getenv不是线程安全的。涉及到多个语言runtime读写env了。倒霉赶上了属于是

How to Simplify Object Comparisons with Ties in C++11/14

省流,tie

代码语言:javascript
代码运行次数:0
复制
struct Person
{
    std::string first_name;
    std::string last_name;
    std::uint8_t age;

    auto tied() const
    {
        returnstd::tie(first_name, last_name, age);
    }

    booloperator==(const Person& other) const
    {
        return tied() == other.tied();
    }

    booloperator<(const Person& other) const
    {
        return tied() < other.tied();
    }
};
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-02-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CPP每周推送 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章
    • C++26: attributes in structured bindings
    • A pattern for obtaining a single value while holding a lock
    • PPSSPP or psp? Uncovering bugs from the past
    • C stdlib isn’t threadsafe and even safe Rust didn’t save us
    • How to Simplify Object Comparisons with Ties in C++11/14
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档