分类 技术 下的文章

Ubuntu 21.10 “Impish Indri” 刚刚发布。如果你正在使用 Ubuntu 21.04,你应该有升级到 Ubuntu 21.10 的选项。

然而,这种推出将是逐步的。这意味着不是每个人都会立即得到新版本可用的通知。在你看到升级选项之前,可能需要几周的时间。

但是,如果你迫不及待地想获得带有 GNOME 40 和其他新功能的 Ubuntu 21.10 呢?你真的需要等待吗?不用。

现在就从 Ubuntu 21.04 升级到 Ubuntu 21.10

以下是你要做的。打开“ 软件和更新 Software & Updates ”应用:

Start the Software & Updates application

并确保你在“ 更新 Updates ”标签下将“ 通知我新的 Ubuntu 版本 Notify me of a new Ubuntu version ”设置为“ 任何新版本 For any new version ”。

Make sure that settings are right for new Ubuntu version notification

现在打开终端,输入以下命令,以确保你的系统已经更新:

sudo apt update && sudo apt upgrade

当你的 Ubuntu 21.04 系统安装了所有的更新,运行更新管理器来寻找开发版本(本例中为 Ubuntu 21.10)。

update-manager -d

它将打开寻找更新的“ 更新管理器 Update Manager ”。由于你已经更新了系统,它不会找到新的更新来安装。然而,它将看到 Ubuntu 21.10 现在已经可用。

Hit the upgrade button

你可以点击“ 升级 Upgrade ”按钮,按照屏幕上的选项开始升级程序。你需要有良好的网络速度来下载 2GB 的更新。确保你的系统在升级过程中保持与电源的连接。

享受 Ubuntu 21.10!

(题图:discourse.ubuntu.com


via: https://itsfoss.com/upgrade-ubuntu-to-newer-version/

作者:Abhishek Prakash 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

售价 399 美元的 PinePhone Pro 是一款 Linux 智能手机,或许有潜力取代一些预算相当的 Android 设备。但作为消费者,还需要等待几个月。

早在 2019 年,当 Pine64 宣布推出 PinePhone 时,没有人想到它会变得如此受欢迎。在短短两年间,Pine64 已经成功建立了一个由数万名开发者和用户组成的社区,大家一起努力使 Linux 完美地跑在了手机上。

现在,随着 PinePhone Pro 的宣布,Pine64 正在扩大 Linux 手机的受众范围。这个设备有许多令人难以置信的新功能,所有这些都使它可以与许多中档 Android 手机相提并论。

PinePhone Pro 功能

与原来的 PinePhone 相比,PinePhone Pro 带来了巨大的升级。这些升级中最值得注意的是使用了 Rockchip 的六核 RK3399S SoC 芯片,这应该能显著地提升性能。其他一些值得注意的功能和升级还有:

  • 4GB LPDDR4 内存
  • 128GB 存储 + microSD 卡插槽
  • 6 英寸 IPS 显示屏,采用 大猩猩 4 号玻璃
  • 1300 万像素(后置)+ 500 万像素(前置)的摄像头

让我们来探讨一下这方面的更多细节。

性能更好

到目前为止,最重要的升级是 RK3399S SoC 的加入,它是 Pine64 和 Rockchip 合作的结果。这个令人印象深刻的强大 SoC 包含 6 个 CPU 核心,以及一个四核 Mali T860 GPU。

这一组合带来了显著的性能提升,使得 PinePhone Pro 的性能与大多数中档安卓手机相当。这带来了一个更快的系统,能够运行许多桌面级应用程序,如用于照片编辑的 GIMP 和用于仿真游戏的 RetroArch。

总的来说,这次升级将大大改善开发者和消费者的用户体验。

内存更多

考虑到智能手机已经开始提供 6GB 内存作为基本变体时,Linux 智能手机也应该使用更多的内存来保持流畅。虽然在优化方面已经做了很多工作,但更多的内存总是有益的。

PinePhone Pro 提供了 4GB 的内存,当放在基座上时可以有更大的通用性,当作为手机使用时可以多打开几个应用程序。我对此感到非常兴奋,因为它应该能够模拟更多的游戏,增加 PinePhone Pro 作为娱乐设备的吸引力。

存储空间升级

我的原版的 PinePhone 面临的最大挑战之一是存储空间不足。从看电影到玩仿真游戏,我不得不不断地删除文件以获得足够的存储空间。

然而,在 PinePhone Pro 上,Pine64 已经解决了这个问题,它提供了 128GB 的闪存,这对任何人来说都足够了。

显示屏改进

虽然这并不是原版 PinePhone 的痛点,但 PinePhone Pro 的显示屏已经升级,变得更大,采用了大猩猩 4 号玻璃。这是非常值得欢迎的,这款手机现在应该可以提供明显改善的防刮伤性能和更多可用的屏幕空间。

虽然 AMOLED 面板会很好,但这在一定程度上会提高价格,可能会降低设备的吸引力。总的来说,我对这次升级很满意,我相信许多用户也是这样。

相机升级

至少对我来说,原版的 PinePhone 的摄像头是一个相当大的痛点。主摄像头只有 500 万像素,还有一个小小的 200 万像素的前置摄像头,这两个摄像头都不能拍出非常高质量的图像。

原版的 PinePhone 的主摄像头已被移到 PinePhone Pro 的前面。它与一个 1300 万像素的索尼摄像头传感器相配,能够录制 4K 视频和提供更高的图像质量。

用户终于可以用他们的 Linux 智能手机来拍摄照片,在社交媒体平台上分享了。

你可以升级你的原版 PinePhone 吗?

这是我看到该公告时问的第一个问题。不幸的是,将你的 PinePhone 升级到 PinePhone Pro 主板是不可行的。我认为 Pine64 解释得很好:

虽然 PinePhone Pro 的主板尺寸适合 PinePhone,但机框、IPS 显示面板、摄像头、子板和散热系统都不同。例如,PinePhone Pro 的摄像头就不适合 PinePhone 的机框,而且与 PinePhone Pro 的主板在电气上不兼容。散热是另一个重要的考虑因素,因为在原来的 PinePhone 的机框中,较高的热量输出可能不能简单地忽略,这需要克服解决。

虽然 Pine64 不建议升级你原来的 PinePhone 的主板,但我认为尝试一下还是很有意思的。虽然令人失望,但也应该注意到,Pine64 并不打算停止原来的 PinePhone 开发,因为它对于想要一个便宜的 Linux 手机作为基本用途的人来说是完美的。

总结

总的来说,我非常兴奋地看到又一个设备进入 Linux 手机市场,尤其是像 PinePhone Pro 这样将得到良好支持(希望是这样)的设备。尽管其价格是 399 美元,但我认为很多人都会蜂拥而至购买这款手机。

如果你认为你可能是这些人中的一员,但你得等待几个月后的正式发布。

然而,想要获得早期设备的开发者现在可以点击下面的按钮来预购 PinePhone Pro。

关于 PinePhone Pro 的可用性和规格的更多细节,你应该去他们的 官方网站 看看。

你要买 PinePhone Pro 吗?请在下面的评论中告诉我!


via: https://news.itsfoss.com/pinephone-pro-introduced/

作者:Jacob Crume 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

主机名是人类用来指代特定计算机的标签。

 title=

计算机有网络地址,但人类通常很难记住它们。主机名是帮助人类参考特定计算机的标签。例如,你可能不会导航到 192.168.1.4,而是导航到 linuxlaptoplinuxlaptop.local

地址和名称

所有联网的计算机(也被称为 主机 host )都需要一个地址:一个与之相关的唯一数字,以使数据报文能够在它们之间进行正确的数据通信。这就是所谓的 互联网协议 Internet Protocol (IP)地址。数字 54.204.39.132 是一个 互联网协议第四版 Internet Protocol version 4 (IPv4)地址。较新的 IPv6 地址要长得多,像这样:2001:0db6:3c4d:0017:0000:0000:2a2f:1a2b。 哇!这将是很难记住的!

$ ip addr show

计算机也可以被赋予标签。被称为 主机名 hostname ,这些是友好的名称,便于参考。我可以把我的计算机的主机名设置为 copperhead。只要这个名字在网络上是唯一的,所有其他用户和计算机都可以把 copperhead 作为地址,而不是 IP 地址。

$ hostname -s

你可以更新你的计算机的主机名。

阅读 Seth Kenlon 的文章 如何在 Linux 上更改主机名,了解如何在 Linux 上这样做。

完全限定域名

从技术上讲,主机名包括一个域名。如果我的域名是 mycompany.com,那么我的计算机的主机名是 copperhead.mycompany.com,以句点分隔。这就形成了一个 完全限定域名 fully qualified domain name (FQDN)。这很重要,因为 IP 地址可以解析为 FQDN。

host.domain.topleveldomain

例如:www.example.com 是一个完全限定域名。

你的域名一般已经确定了,所以你只负责提供主机部分。本文的重点是主机。

名称解析

将 IP 地址转换为相应的主机名的过程被称为名称解析。这个过程首先发生在本地主机表中。Linux 使用文件 /etc/hosts 来存储这个表。

cat /etc/hosts

还有一个分层的、去中心化的基于网络的系统提供解析,称为 域名系统 Domain Name System (DNS)。这时 FQDN 变得非常重要。

$ dig www.opensource.com

名称的乐趣

为我们的计算机起名字可能很有趣。如果你有很多,你可以使用一个主题。我曾经为一家公司工作,该公司将所有的服务器都以蛇命名。

后来我工作的一家公司,我是一个数据中心经理,使用啤酒品牌。当我们收到一个新的服务器时,这很令人兴奋,因为我会给开发团队发邮件征求建议。我们大约有 100 台服务器。这些提供了一个有趣的清单,反映了公司的多样性。我们有从库尔斯和百威到阿姆斯特尔和浅粉象的一切。我们有虎牌啤酒、胜狮啤酒和札幌啤酒等等!

我们认为这很酷!然后,想象一下,当你试图记住卢云堡是拥有最多内存的虚拟化服务器,佩罗尼是 SQL 数据库服务器,喜力是新的域控制器时,会发生什么,特别是对于一个快速发展的公司的新员工。

惯例

当然,主机名是所有者的选择,所以请尽情发挥。然而,根据环境的不同,使用容易记忆的名字或基于命名惯例的名字可能更有意义,因为这些名字有利于描述主机。

有用的名字

如果你想放弃有趣的东西,并对你的系统进行有益的命名,也许可以考虑它们的功能。数据库服务器可以被命名为 database1database2database3 等等。Web 服务器可以命名为 webserver1webserver2 等等。

位置名称

我在许多客户那里使用了一种技术,用一组字符的位置来命名服务器主机,这些字符描述了该系统的一个方面,有助于识别。例如,如果我正在为内政部(DOI)开发一个业务流程管理(BPM)系统,我就会在命名规则中加入他们的缩写词。

此外,就像许多大型企业、金融机构和政府一样,他们可能有不同的数据中心,位于不同的地理位置,以达到性能或灾难恢复的目的。因此,比如说,位于北美大陆东海岸的数据中心被称为 ED(East Data center),而位于西海岸的数据中心则是 WD(West Data center)。

所有这些信息将汇集到一个名称中,如 doibpm1eddoibpm1wd。因此,虽然这些名字看起来不长,但在这个项目上工作的人可以很容易地识别它们的目的和位置,而且这个名字甚至可以对潜在的恶意者混淆它们的用途。换句话说,业主可以选择只对内部人员有意义的命名方式

互联网标准

有几个标准管理着主机名。你可以在 互联网工程任务组 Internet Engineering Task Force (IETF)维护的 意见征求 Requests for Comment (RFC)中找到这些标准。由此,请遵守以下规定:

  • 主机名的长度应该在 1 到 63 个 ASCII 字符之间
  • 一个 FQDN 的最大长度为 253 个 ASCII 字符
  • 不区分大小写
  • 允许的字符:az09-(连字符),和 _(下划线)。

我希望这篇文章能帮助你澄清主机名。玩得开心,发挥创意。


via: https://opensource.com/article/21/10/what-hostname

作者:Alan Formy-Duval 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Debian 和基于 Debian 的 Kali Linux 将 Firefox 作为默认的网页浏览器。但这并不意味着你不能在其中安装其他网页浏览器。

Chrome 浏览器非常流行,你可能已经在其他系统上使用它了。如果你想在 Debian 上安装 Chrome,你肯定可以这样做。

你在 Debian 的软件库中找不到 Chrome,因为它不是开源软件,但你可以从 Chrome 网站下载并安装它。

在本教程中,我将向你展示在 Debian 上安装 Chrome 的两种方法:

  • GUI 方法
  • 命令行方法

让我们先从 GUI 方法开始。

注意:我在这里的例子中使用的是 Debian,但由于 Kali Linux 是基于 Debian 的,所以同样的方法也适用于 Kali Linux。

方法 1: 在 Debian 上以图形方式安装 Chrome 浏览器

这是一个不费吹灰之力的方法。你去 Chrome 网站,下载 deb 文件,然后双击它来安装它。我将详细地展示这些步骤,这样你就能很容易地掌握了。

前往 Chrome 的网站。

Get Google Chrome

你会看到下载 Chrome 的选项。

Click on the Download Chrome button

当你点击下载按钮时,它会给你两个下载安装文件的选项。选择写着 Debian/Ubuntu 的那个。

Download the Chrome installer file for Debian

请注意,Chrome 浏览器不适用于 32 位系统。

接下来,你应该选择将文件保存到电脑中,而不是在软件中心打开进行安装。这样一来,下载的文件将被保存在下载文件夹中,而不是临时目录中。

Save the downloaded DEB file for Google Chrome

进入下载文件夹,右击下载的 DEB 文件,选择用 “Software Install” 打开它。

Right click on the downloaded DEB file and open with Software Install

它将打开软件中心,你应该看到现在安装 Chrome 浏览器的选项。点击安装按钮。

Click on the install button

你会被要求输入账户的密码。这是你用来登录系统的同一密码。

Enter your account’s password

在不到一分钟的时间里,Chrome 就会安装完毕。你现在应该看到一个删除选项,这表明软件已经安装完毕。

Chrome is now installed

当 Chrome 在 Debian 上安装完毕,在系统菜单中搜索它并启动它。

Start Google Chrome

它将要求成为你的默认浏览器,并将崩溃报告发送给谷歌。你可以取消勾选这两个选项。然后你就可以看到谷歌浏览器的窗口。

如果你登录了你的谷歌账户,你应该可以在这里同步你的密码、书签和其他浏览数据。好好体验吧!

还有一点,安装完 Chrome 后,你可以从系统中删除下载的 DEB 文件。不再需要它了,甚至在卸载 Chrome 时也不需要。

方法 2:在 Debian 上从终端安装 Chrome

你刚才看到的内容可以在终端中轻松实现。

首先,确保你的软件包缓存已经刷新,并且你已经安装了 wget,用于 在终端中从网上下载文件

sudo apt update && sudo apt install wget

接下来是下载 Chrome 的 .deb 文件。

wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb

下载后,你可以用 apt 命令 在终端安装 deb 文件,像这样:

sudo apt install ./google-chrome-stable_current_amd64.deb

安装完成后,你就可以开始使用 Chrome 了。

额外提示:更新 Chrome

这两种方法都会将谷歌的软件库添加到你的系统中。你可以在你的 sources.list.d 目录中看到它:

cat /etc/apt/sources.list.d/google-chrome.list

这意味着 Chrome 将与 Debian 和 Kali Linux 中的其他系统更新一起被更新。你知道 如何在命令行中更新你的 Kali Linux 或 Debian 系统么?只要使用这个命令:

sudo apt update && sudo apt upgrade -y

从你的系统中卸载 Chrome

即使你选择用 GUI 方法在 Debian 上安装 Chrome,你也必须使用终端来删除它。

不要担心。这其实只是一个命令:

sudo apt purge google-chrome-stable

根据要求输入你的账户密码。当你输入密码时,屏幕上没有任何显示。这没关系。输入它并按回车键,确认删除。

好了,就这些了。我希望你觉得这个教程有帮助。


via: https://itsfoss.com/install-chrome-debian-kali-linux/

作者:Abhishek Prakash 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

增强 C 语言程序的弹性和可靠性的五种方法。

 title=

即使是最好的程序员也无法完全避免错误。这些错误可能会引入安全漏洞、导致程序崩溃或产生意外操作,具体影响要取决于程序的运行逻辑。

C 语言有时名声不太好,因为它不像近期的编程语言(比如 Rust)那样具有内存安全性。但是通过额外的代码,一些最常见和严重的 C 语言错误是可以避免的。下文讲解了可能影响应用程序的五个错误以及避免它们的方法:

1、未初始化的变量

程序启动时,系统会为其分配一块内存以供存储数据。这意味着程序启动时,变量将获得内存中的一个随机值。

有些编程环境会在程序启动时特意将内存“清零”,因此每个变量都得以有初始的零值。程序中的变量都以零值作为初始值,听上去是很不错的。但是在 C 编程规范中,系统并不会初始化变量。

看一下这个使用了若干变量和两个数组的示例程序:

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

int
main()
{
  int i, j, k;
  int numbers[5];
  int *array;

  puts("These variables are not initialized:");

  printf("  i = %d\n", i);
  printf("  j = %d\n", j);
  printf("  k = %d\n", k);

  puts("This array is not initialized:");

  for (i = 0; i < 5; i++) {
    printf("  numbers[%d] = %d\n", i, numbers[i]);
  }

  puts("malloc an array ...");
  array = malloc(sizeof(int) * 5);

  if (array) {
    puts("This malloc'ed array is not initialized:");

    for (i = 0; i < 5; i++) {
      printf("  array[%d] = %d\n", i, array[i]);
    }

    free(array);
  }

  /* done */

  puts("Ok");
  return 0;
}

这个程序不会初始化变量,所以变量以系统内存中的随机值作为初始值。在我的 Linux 系统上编译和运行这个程序,会看到一些变量恰巧有“零”值,但其他变量并没有:

These variables are not initialized:
  i = 0
  j = 0
  k = 32766
This array is not initialized:
  numbers[0] = 0
  numbers[1] = 0
  numbers[2] = 4199024
  numbers[3] = 0
  numbers[4] = 0
malloc an array ...
This malloc'ed array is not initialized:
  array[0] = 0
  array[1] = 0
  array[2] = 0
  array[3] = 0
  array[4] = 0
Ok

很幸运,ij 变量是从零值开始的,但 k 的起始值为 32766。在 numbers 数组中,大多数元素也恰好从零值开始,只有第三个元素的初始值为 4199024。

在不同的系统上编译相同的程序,可以进一步显示未初始化变量的危险性。不要误以为“全世界都在运行 Linux”,你的程序很可能某天在其他平台上运行。例如,下面是在 FreeDOS 上运行相同程序的结果:

These variables are not initialized:
  i = 0
  j = 1074
  k = 3120
This array is not initialized:
  numbers[0] = 3106
  numbers[1] = 1224
  numbers[2] = 784
  numbers[3] = 2926
  numbers[4] = 1224
malloc an array ...
This malloc'ed array is not initialized:
  array[0] = 3136
  array[1] = 3136
  array[2] = 14499
  array[3] = -5886
  array[4] = 219
Ok

永远都要记得初始化程序的变量。如果你想让变量将以零值作为初始值,请额外添加代码将零分配给该变量。预先编好这些额外的代码,这会有助于减少日后让人头疼的调试过程。

2、数组越界

C 语言中,数组索引从零开始。这意味着对于长度为 10 的数组,索引是从 0 到 9;长度为 1000 的数组,索引则是从 0 到 999。

程序员有时会忘记这一点,他们从索引 1 开始引用数组,产生了 “大小差一” off by one 错误。在长度为 5 的数组中,程序员在索引“5”处使用的值,实际上并不是数组的第 5 个元素。相反,它是内存中的一些其他值,根本与此数组无关。

这是一个数组越界的示例程序。该程序使用了一个只含有 5 个元素的数组,但却引用了该范围之外的数组元素:

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

int
main()
{
  int i;
  int numbers[5];
  int *array;

  /* test 1 */

  puts("This array has five elements (0 to 4)");

  /* initalize the array */
  for (i = 0; i < 5; i++) {
    numbers[i] = i;
  }

  /* oops, this goes beyond the array bounds: */
  for (i = 0; i < 10; i++) {
    printf("  numbers[%d] = %d\n", i, numbers[i]);
  }

  /* test 2 */

  puts("malloc an array ...");

  array = malloc(sizeof(int) * 5);

  if (array) {
    puts("This malloc'ed array also has five elements (0 to 4)");

    /* initalize the array */
    for (i = 0; i < 5; i++) {
      array[i] = i;
    }

    /* oops, this goes beyond the array bounds: */
    for (i = 0; i < 10; i++) {
      printf("  array[%d] = %d\n", i, array[i]);
    }

    free(array);
  }

  /* done */

  puts("Ok");
  return 0;
}

可以看到,程序初始化了数组的所有值(从索引 0 到 4),然后从索引 0 开始读取,结尾是索引 9 而不是索引 4。前五个值是正确的,再后面的值会让你不知所以:

This array has five elements (0 to 4)
  numbers[0] = 0
  numbers[1] = 1
  numbers[2] = 2
  numbers[3] = 3
  numbers[4] = 4
  numbers[5] = 0
  numbers[6] = 4198512
  numbers[7] = 0
  numbers[8] = 1326609712
  numbers[9] = 32764
malloc an array ...
This malloc'ed array also has five elements (0 to 4)
  array[0] = 0
  array[1] = 1
  array[2] = 2
  array[3] = 3
  array[4] = 4
  array[5] = 0
  array[6] = 133441
  array[7] = 0
  array[8] = 0
  array[9] = 0
Ok

引用数组时,始终要记得追踪数组大小。将数组大小存储在变量中;不要对数组大小进行 硬编码 hard-code 。否则,如果后期该标识符指向另一个不同大小的数组,却忘记更改硬编码的数组长度时,程序就可能会发生数组越界。

3、字符串溢出

字符串只是特定类型的数组。在 C 语言中,字符串是一个由 char 类型值组成的数组,其中用一个零字符表示字符串的结尾。

因此,与数组一样,要注意避免超出字符串的范围。有时也称之为 字符串溢出

使用 gets 函数读取数据是一种很容易发生字符串溢出的行为方式。gets 函数非常危险,因为它不知道在一个字符串中可以存储多少数据,只会机械地从用户那里读取数据。如果用户输入像 foo 这样的短字符串,不会发生意外;但是当用户输入的值超过字符串长度时,后果可能是灾难性的。

下面是一个使用 gets 函数读取城市名称的示例程序。在这个程序中,我还添加了一些未使用的变量,来展示字符串溢出对其他数据的影响:

#include <stdio.h>
#include <string.h>

int
main()
{
  char name[10];                       /* Such as "Chicago" */
  int var1 = 1, var2 = 2;

  /* show initial values */

  printf("var1 = %d; var2 = %d\n", var1, var2);

  /* this is bad .. please don't use gets */

  puts("Where do you live?");
  gets(name);

  /* show ending values */

  printf("<%s> is length %d\n", name, strlen(name));
  printf("var1 = %d; var2 = %d\n", var1, var2);

  /* done */

  puts("Ok");
  return 0;
}

当你测试类似的短城市名称时,该程序运行良好,例如伊利诺伊州的 Chicago 或北卡罗来纳州的Raleigh

var1 = 1; var2 = 2
Where do you live?
Raleigh
<Raleigh> is length 7
var1 = 1; var2 = 2
Ok

威尔士的小镇 Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch 有着世界上最长的名字之一。这个字符串有 58 个字符,远远超出了 name 变量中保留的 10 个字符。结果,程序将值存储在内存的其他区域,覆盖了 var1var2 的值:

var1 = 1; var2 = 2
Where do you live?
Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch
<Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch> is length 58
var1 = 2036821625; var2 = 2003266668
Ok
Segmentation fault (core dumped)

在运行结束之前,程序会用长字符串覆盖内存的其他部分区域。注意,var1var2 的值不再是起始的 12

避免使用 gets 函数,改用更安全的方法来读取用户数据。例如,getline 函数会分配足够的内存来存储用户输入,因此不会因输入长值而发生意外的字符串溢出。

4、重复释放内存

“分配的内存要手动释放”是良好的 C 语言编程原则之一。程序可以使用 malloc 函数为数组和字符串分配内存,该函数会开辟一块内存,并返回一个指向内存中起始地址的指针。之后,程序可以使用 free 函数释放内存,该函数会使用指针将内存标记为未使用。

但是,你应该只使用一次 free 函数。第二次调用 free 会导致意外的后果,可能会毁掉你的程序。下面是一个针对此点的简短示例程序。程序分配了内存,然后立即释放了它。但为了模仿一个健忘但有条理的程序员,我在程序结束时又一次释放了内存,导致两次释放了相同的内存:

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

int
main()
{
  int *array;

  puts("malloc an array ...");

  array = malloc(sizeof(int) * 5);

  if (array) {
    puts("malloc succeeded");

    puts("Free the array...");
    free(array);
  }

  puts("Free the array...");
  free(array);

  puts("Ok");
}

运行这个程序会导致第二次使用 free 函数时出现戏剧性的失败:

malloc an array ...
malloc succeeded
Free the array...
Free the array...
free(): double free detected in tcache 2
Aborted (core dumped)

要记得避免在数组或字符串上多次调用 free。将 mallocfree 函数定位在同一个函数中,这是避免重复释放内存的一种方法。

例如,一个纸牌游戏程序可能会在主函数中为一副牌分配内存,然后在其他函数中使用这副牌来玩游戏。记得在主函数,而不是其他函数中释放内存。将 mallocfree 语句放在一起有助于避免多次释放内存。

5、使用无效的文件指针

文件是一种便捷的数据存储方式。例如,你可以将程序的配置数据存储在 config.dat 文件中。Bash shell 会从用户家目录中的 .bash_profile 读取初始化脚本。GNU Emacs 编辑器会寻找文件 .emacs 以从中确定起始值。而 Zoom 会议客户端使用 zoomus.conf 文件读取其程序配置。

所以,从文件中读取数据的能力几乎对所有程序都很重要。但是假如要读取的文件不存在,会发生什么呢?

在 C 语言中读取文件,首先要用 fopen 函数打开文件,该函数会返回指向文件的流指针。你可以结合其他函数,使用这个指针来读取数据,例如 fgetc 会逐个字符地读取文件。

如果要读取的文件不存在或程序没有读取权限,fopen 函数会返回 NULL 作为文件指针,这表示文件指针无效。但是这里有一个示例程序,它机械地直接去读取文件,不检查 fopen 是否返回了 NULL

#include <stdio.h>

int
main()
{
  FILE *pfile;
  int ch;

  puts("Open the FILE.TXT file ...");

  pfile = fopen("FILE.TXT", "r");

  /* you should check if the file pointer is valid, but we skipped that */

  puts("Now display the contents of FILE.TXT ...");

  while ((ch = fgetc(pfile)) != EOF) {
    printf("<%c>", ch);
  }

  fclose(pfile);

  /* done */

  puts("Ok");
  return 0;
}

当你运行这个程序时,第一次调用 fgetc 会失败,程序会立即中止:

Open the FILE.TXT file ...
Now display the contents of FILE.TXT ...
Segmentation fault (core dumped)

始终检查文件指针以确保其有效。例如,在调用 fopen 打开一个文件后,用类似 if (pfile != NULL) 的语句检查指针,以确保指针是可以使用的。

人都会犯错,最优秀的程序员也会产生编程错误。但是,遵循上面这些准则,添加一些额外的代码来检查这五种类型的错误,就可以避免最严重的 C 语言编程错误。提前编写几行代码来捕获这些错误,可能会帮你节省数小时的调试时间。


via: https://opensource.com/article/21/10/programming-bugs

作者:Jim Hall 选题:lujun9972 译者:unigeorge 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

OpenPGP.js 是一个实现了 OpenPGP 标准的密码学库,最常用于电子邮件加密。

 title=

OpenPGP.js 是一个实现了 OpenPGP 标准 的密码学库,最常用于电子邮件加密。ProtonMail、Mailvelope 和 FlowCrypt 都使用 OpenPGP.js,这还仅仅是其中一些。也就是说 OpenPGP.js 库对数百万用户的信息进行了加密。

OpenPGP 标准首次发布于 20 世纪 90 年代,像几乎任何东西一样,需要维护和更新,以保证安全和可用性。该标准的“加密刷新” 正在进行中,它增加了现代的加密算法并废除了过时的算法。为了提高可用性,各种电子邮件应用程序现在允许用户无缝加密他们的通信,用户无需管理他们的密钥或他们的联系人的密钥。

OpenPGP.js 于 2014 年首次发布,开始基于一个名为 GPG4Browsers 的早期原型,该原型基于 Herbert Hanewinkel(以及其他贡献者)的几个脚本。OpenPGP.js 的第二个版本于 2016 年发布,完全重新设计,使用 Uint8Arrays 而不是字符串(这大大增加了其性能),并在内部使用现代 ES6 模块而不是 CommonJS 模块。第 3 和第 4 版都是在 2018 年发布的,分别增加了对椭圆曲线加密法(ECC)和流的支持。

我和我的团队继续在 OpenPGP.js 上工作,以确保其发展为一个易于使用的强加密库。

1、默认的椭圆曲线加密

在 OpenPGP.js 第 4 版中,生成新密钥时默认使用 RSA。虽然 ECC 更快、更安全,但 Curve25519 还没有在 OpenPGP 规范中得到标准化。加密刷新草案包括了 Curve25519,并且预计它将“按原样”包含在下一版本的 OpenPGP 规范中,因此 OpenPGP.js 第 5 版现在默认使用 ECC 生成密钥。

2、只导入你需要的模块

同样,虽然 OpenPGP.js 内部使用 ES6 模块多年,但第 4 版仍然没有发布一个合适的 ES6 模块。相反,它只发布了一个 通用模块定义 Univeral Module Definition (UMD)模块,可以在浏览器和 Node.js 上运行。在第 5 版中,这种情况有所改变,为浏览器和 Node.js 发布了单独的模块(包括 ES6 和非 ES6),使库用户更容易在所有平台上导入 OpenPGP.js ,且(当使用 ES6 模块时)只导入他们需要的部分。这在很大程度上是通过将构建系统切换到 rollup 来实现的。

3、拒绝弱加密技术

还有许多其他的安全改进。例如,1024 位 RSA 密钥、ElGamal 和 DSA 密钥被认为是不安全的,并被默认拒绝。此外,第 4 版已经默认使用 AES 加密,第 5 版现在完全默认拒绝使用较弱的算法进行加密,即使公钥声称只支持较弱的算法。相反,它假定所有的 OpenPGP 实现都支持 AES(这种情况已经存在很长时间了)。

OpenPGP.js 的下一步是什么?

展望未来,有一些安全方面的改进要做。用于识别公钥的密钥指纹仍然使用 SHA-1,尽管在加密技术更新中计划对此进行修复。同时,建议使用不同的方法来确定用于加密的任何公钥的真实性,例如使用提议的 网络密钥目录 Web Key Directory (WKD)标准直接从收件人的域中获取整个密钥,这已经由各种 电子邮件提供商 实现。WKD 支持内置于 OpenPGP.js 第 4 版,但在第 5 版中是一个单独的模块,以保持主库的精简。

同样,当用密码而不是公钥加密信息或文件时(例如:在使用 OpenPGP 进行电子邮件加密时不常见,但在用于加密备份时更常见),密码会使用相对较弱的 密钥衍生函数 Key Derivation Function (KDF)转换为对称密钥。因此,建议应用在将用户的密码传递给 OpenPGP.js 之前,先通过一个强大的 KDF,如 Argon2scrypt。希望加密刷新草案会包括这些算法中的一种,以便在未来的 OpenPGP.js 版本中实现。

如何使用 OpenPGP.js 第 5 版

不过现在,OpenPGP.js 第 5 版已经 发布 到 npm 仓库。如果你喜欢,可以随时试用!欢迎在 GitHub 的 讨论版 中进行反馈。然而,请注意,虽然 OpenPGP.js 是一个通用的加密库,但它的主要使用情况是在需要与 OpenPGP 规范兼容的情况下(例如,在发送或接收 PGP 加密的电子邮件时)。对于其他的使用情况,不同的库可能是一个更合适或性能更好的选择。当然,总的来说,在尝试使用任何加密技术时都要小心。

感谢阅读,这里是保护电子邮件的未来!


via: https://opensource.com/article/21/10/openpgpjs

作者:Daniel Huigens 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出